﻿#undef Debug
using System;
using System.Collections;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Reflection;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Xml;
using System.Xml.Serialization;
using System.Drawing;
using System.Globalization;

namespace InkFx.WinControl.Utils
{
    internal static class Tools
    {
        #region  32&64位 程序集 控制

        /// <summary>
        /// 判断当前进程 是否是 64位进程
        /// </summary>
        public static bool Is64BitProcess
        {
            get
            {
                bool is64Proc = (IntPtr.Size == 8);
                return is64Proc;
            }
        }
        /// <summary>
        /// 判断当前操作系统 是否是 64位系统
        /// </summary>
        public static bool Is64BitOperatingSystem
        {
            get
            {
                bool is64BitProc = Is64BitProcess;
                if (is64BitProc)    //如果当前是 64位进程, 则为 64位系统
                    return true;
                else                //如果当前是 32位进程, 则判断 是否运行在 64位系统的模拟器上
                {
                    //Win32 函数 IsWow64Process
                    //如果该进程是32位进程，运行在64操作系统下，该值为true，否则为false。
                    //如果该进程是一个64位应用程序，运行在64位系统上，该值也被设置为false。

                    bool flag;
                    return DoesWin32MethodExist("kernel32.dll", "IsWow64Process") && IsWow64Process(GetCurrentProcess(), out flag) && flag;
                }
            }
        }

        /// <summary>
        /// 判断当前进程 是否是 基于 .Net Framework 2.0 在运行 (.Net 3.5 属于此类)
        /// </summary>
        public static bool IsDotNetFx20
        {
            get
            {
                Version version = Environment.Version;
                return version.Major == 2;
            }
        }
        /// <summary>
        /// 判断当前进程 是否是 基于 .Net Framework 4.0 在运行
        /// </summary>
        public static bool IsDotNetFx40
        {
            get
            {
                Version version = Environment.Version;
                return version.Major == 4;
            }
        }

        /// <summary>
        /// 获取当前 操作系统 版本信息
        /// </summary>
        public static OperatingSystem OSVersion
        {
            get { return Environment.OSVersion; }
        }

        private static bool DoesWin32MethodExist(string moduleName, string methodName)
        {
            IntPtr moduleHandle = GetModuleHandle(moduleName);
            if (moduleHandle == IntPtr.Zero)
            {
                return false;
            }
            IntPtr procAddress = GetProcAddress(moduleHandle, methodName);
            return procAddress != IntPtr.Zero;
        }
        [DllImport("kernel32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool IsWow64Process([In] IntPtr hSourceProcessHandle, [MarshalAs(UnmanagedType.Bool)] out bool isWow64);
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
        [DllImport("kernel32.dll", BestFitMapping = false, CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr GetModuleHandle(string moduleName);
        [DllImport("kernel32.dll", BestFitMapping = false, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
        private static extern IntPtr GetProcAddress(IntPtr hModule, string methodName);
        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr GetCurrentProcess();

        #endregion


        #region  运 行 平 台 环 境

        private static string m_AppFolder = string.Empty;
        /// <summary>
        /// 当前程序工作基本目录
        /// </summary>
        public static string AppFolder
        {
            get
            {
                if (string.IsNullOrEmpty(m_AppFolder))
                {
#if (!WindowsCE && !PocketPC)
                    m_AppFolder = AppDomain.CurrentDomain.BaseDirectory;
#endif
#if (WindowsCE || PocketPC)
                    m_AppFolder = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().ManifestModule.FullyQualifiedName);
#endif
                }
                return m_AppFolder;
            }
        }

        ///// <summary>
        ///// 当前 进程 所寄宿的 运行平台
        ///// </summary>
        //public static RunPlatform HostPlatform
        //{
        //    get
        //    {
        //        if (Console.In != null && Console.In != StreamReader.Null) return RunPlatform.Console;
        //        if (System.Windows.Forms.Application.OpenForms.Count >= 1) return RunPlatform.WinForm;
        //        if (System.Web.HttpContext.Current != null) return RunPlatform.Web;

        //        return RunPlatform.None;
        //    }
        //}

        ///// <summary>
        ///// 当前进程 所运行的 平台
        ///// </summary>
        //[Serializable]
        //public enum RunPlatform
        //{
        //    None,
        //    Console,
        //    Web,
        //    WinForm,
        //    WinService,
        //}

        /// <summary>
        /// 表示 当前程序 正在进行 VS调试
        /// </summary>
        public static bool IsVSHostDebug
        {
            get
            {
                Process processes = Process.GetCurrentProcess();
                string processName = processes.ProcessName;
                return processName.EndsWith(".vshost", StringComparison.CurrentCultureIgnoreCase)
                    || processName.EndsWith(".vshost.exe", StringComparison.CurrentCultureIgnoreCase);
            }
        }


        private static byte m_IsConsole = 255;
        /// <summary>
        /// 当前程序运行是否显示着控制台 (黑窗口)
        /// </summary>
        public static bool IsConsole
        {
            get
            {
                if (m_IsConsole == 255)
                    m_IsConsole = (Console.In != null && Console.In != StreamReader.Null) ? (byte)1 : (byte)0;
                return m_IsConsole == 1;
            }
        }

        #endregion


        #region  数 据 类 型 和 动 态 赋 值 取 值

        public static bool SetHashValue(IDictionary hash, string key, object value)
        {
            try
            {
                if (hash != null && !string.IsNullOrEmpty(key))
                {
                    if (hash.Contains(key)) hash[key] = value;
                    else hash.Add(key, value);
                    return true;
                }
                return false;
            }
            catch (System.Threading.ThreadAbortException) { throw; }
            catch (Exception ex) { return false; }
        }
        public static object GetHashValue(IDictionary hash, string key)
        {
            try
            {
                if (hash != null && !string.IsNullOrEmpty(key) && hash.Contains(key))
                    return hash[key];
                return null;
            }
            catch (System.Threading.ThreadAbortException) { throw; }
            catch (Exception) { return null; }
        }

        public static bool SetDataRow(DataRow dataRow, string column, object value)
        {
            try
            {
                if (dataRow != null && !string.IsNullOrEmpty(column))
                {
                    //if (dataRow.Table.Columns.Contains(column))
                    //{
                    //    dataRow[column] = value;
                    //    return true;
                    //}
                    //else return false;

                    dataRow[column] = value;
                    return true;
                }
                return false;
            }
            catch (System.Threading.ThreadAbortException) { throw; }
            catch (Exception) { return false; }
        }
        public static object GetDataRow(DataRow dataRow, string column)
        {
            try
            {
                if (dataRow != null && !string.IsNullOrEmpty(column) /*&& dataRow.Table.Columns.Contains(column)*/)
                    return dataRow[column];
                return null;
            }
            catch (System.Threading.ThreadAbortException) { throw; }
            catch (Exception) { return null; }
        }

        public static bool SetDataRowView(DataRowView dataRowView, string column, object value)
        {
            try
            {
                if (dataRowView != null && !string.IsNullOrEmpty(column))
                {
                    //if (dataRowView.Row.Table.Columns.Contains(column))
                    //{
                    //    dataRowView[column] = value;
                    //    return true;
                    //}
                    //else return false;

                    dataRowView[column] = value;
                    return true;
                }
                return false;
            }
            catch (System.Threading.ThreadAbortException) { throw; }
            catch (Exception) { return false; }
        }
        public static object GetDataRowView(DataRowView dataRowView, string column)
        {
            try
            {
                if (dataRowView != null && !string.IsNullOrEmpty(column) /*&& dataRowView.Row.Table.Columns.Contains(column)*/)
                    return dataRowView[column];
                return null;
            }
            catch (System.Threading.ThreadAbortException) { throw; }
            catch (Exception) { return null; }
        }

        public static bool SetPropertyOrField(object obj, string propOrFieldName, object value)
        {
            try
            {
                PropertyInfo propInfo = obj.GetType().GetProperty(propOrFieldName, Property_Field_BindingFlags);
                if (propInfo != null) { propInfo.SetValue(obj, value, null); return true; }

                FieldInfo fieldInfo = obj.GetType().GetField(propOrFieldName, Property_Field_BindingFlags);
                if (fieldInfo != null) { fieldInfo.SetValue(obj, value); return true; }

                return false;
            }
            catch (System.Threading.ThreadAbortException) { throw; }
            catch (Exception) { return false; }
        }
        public static object GetPropertyOrField(object obj, string propOrFieldName)
        {
            try
            {
                PropertyInfo propInfo = obj.GetType().GetProperty(propOrFieldName, Property_Field_BindingFlags);
                if (propInfo != null) { return propInfo.GetValue(obj, null); }

                FieldInfo fieldInfo = obj.GetType().GetField(propOrFieldName, Property_Field_BindingFlags);
                if (fieldInfo != null) { return fieldInfo.GetValue(obj); }

                return null;
            }
            catch (System.Threading.ThreadAbortException) { throw; }
            catch (Exception) { return null; }
        }


        public static bool SetValue(object obj, string propertyName, object value)
        {
            if (obj == null || string.IsNullOrEmpty(propertyName)) return false;
            if (!propertyName.Contains(".")) return InnerSetValue(obj, propertyName, value);

#if (!WindowsCE && !PocketPC)
            string[] array = propertyName.Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries);
#endif
#if (WindowsCE || PocketPC)
            string[] array = Split(propertyName, ".", StringSplitOptions.RemoveEmptyEntries);
#endif
            if (/*array == null || */array.Length <= 0) return false;

            object tempValue = obj;
            int count = array.Length;
            for (int i = 0; i < count - 1; i++)
            {
                string property = array[i];
                object innerValue = InnerGetValue(tempValue, property);
                if (innerValue == null) return false;
                else tempValue = innerValue;
            }
            return InnerSetValue(tempValue, array[count - 1], value);
        }
        public static object GetValue(object obj, string propertyName)
        {
            if (obj == null || string.IsNullOrEmpty(propertyName)) return null;
            if (!propertyName.Contains(".")) return InnerGetValue(obj, propertyName);

#if (!WindowsCE && !PocketPC)
            string[] array = propertyName.Split(new[] { "." }, StringSplitOptions.RemoveEmptyEntries);
#endif
#if (WindowsCE || PocketPC)
            string[] array = Split(propertyName, ".", StringSplitOptions.RemoveEmptyEntries);
#endif
            if (/*array == null || */array.Length <= 0) return null;

            object tempValue = obj;
            int count = array.Length;
            for (int i = 0; i < count; i++)
            {
                string property = array[i];
                tempValue = InnerGetValue(tempValue, property);
                if (tempValue == null) return null;
            }
            return tempValue;
        }
        public static T GetValue<T>(object obj, string propertyName)
        {
            object result = GetValue(obj, propertyName);
            if (result == null) return default(T);
            if (result is T) return (T)result;
            try
            {
                object value = ChangeType(result, typeof(T));
                return value is T ? (T)value : default(T);
            }
            catch (System.Threading.ThreadAbortException) { throw; }
            catch (Exception) { return default(T); }
        }
        private static bool InnerSetValue(object obj, string propertyName, object value)
        {
            if (obj == null) return false;

            IDictionary hash = obj as IDictionary;
            if (hash != null)
            {
                bool result = SetHashValue(hash, propertyName, value);
                return result;
            }

            DataRow dataRow = obj as DataRow;
            if (dataRow != null)
            {
                bool result = SetDataRow(dataRow, propertyName, value);
                return result;
            }

            DataRowView dataRowView = obj as DataRowView;
            if (dataRowView != null)
            {
                bool result = SetDataRowView(dataRowView, propertyName, value);
                return result;
            }

            bool result2 = SetPropertyOrField(obj, propertyName, value);
            if (result2) return true;

            return false;
        }
        private static object InnerGetValue(object obj, string propertyName)
        {
            if (obj == null) return null;

            IDictionary hash = obj as IDictionary;
            if (hash != null)
            {
                object value = GetHashValue(hash, propertyName);
                return value;
            }

            DataRow dataRow = obj as DataRow;
            if (dataRow != null)
            {
                object value = GetDataRow(dataRow, propertyName);
                return value;
            }

            DataRowView dataRowView = obj as DataRowView;
            if (dataRowView != null)
            {
                object value = GetDataRowView(dataRowView, propertyName);
                return value;
            }

            object result2 = GetPropertyOrField(obj, propertyName);
            if (result2 != null) return result2;


            return null;
        }


        internal const BindingFlags Property_Field_BindingFlags = BindingFlags.IgnoreCase | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance;

        public static PropertyInfo GetPropertyInfo(Type type, string propertyName)
        {
            return type.GetProperty(propertyName, Property_Field_BindingFlags);
        }
        public static List<PropertyInfo> GetPropertyInfos(Type type)
        {
            PropertyInfo[] array = type.GetProperties(Property_Field_BindingFlags);
            return new List<PropertyInfo>(array);
        }
        public static FieldInfo GetFieldInfo(Type type, string fieldName)
        {
            return type.GetField(fieldName, Property_Field_BindingFlags);
        }
        public static List<FieldInfo> GetFieldInfos(Type type)
        {
            FieldInfo[] array = type.GetFields(Property_Field_BindingFlags);
            return new List<FieldInfo>(array);
        }

        #endregion


        #region  对 象 浅 克 隆

        public static T CloneObject<T>(T source) where T : new()
        {
            Type type = source.GetType();
            PropertyInfo[] propertyArray = type.GetProperties();
            FieldInfo[] fieldArray = type.GetFields();
            T target = new T();
            foreach (PropertyInfo property in propertyArray)
            {
                object value = property.GetValue(source, null); 
                property.SetValue(target, value, null);
            }
            foreach (FieldInfo field in fieldArray)
            {
                object value = field.GetValue(source);
                field.SetValue(target, value);
            }
            return target;
        }

        #endregion


        #region  序列化 和 反序列化

        public static byte[] DotNetBinarySerialize(object data)
        {
            return DotNetBinarySerialize(data, false);
        }
        public static byte[] DotNetBinarySerialize(object data, bool throwEeception)
        {
            if (data == null) return null;

            try
            {
                System.Runtime.Serialization.Formatters.Binary.BinaryFormatter formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
                using (MemoryStream rems = new MemoryStream())
                {
                    using (GZipStream zipStream = new GZipStream(rems, CompressionMode.Compress))
                    {
                        formatter.Serialize(zipStream, data);
                        zipStream.Close();
                    }
                    return rems.ToArray();          //GetBuffer()  不是实际长度，而是 2的次方 数目    
                }
            }
            catch (System.Threading.ThreadAbortException) { throw; }
            catch (Exception exp)
            {
                if (throwEeception) throw;
                else
                {
                    string logMsg = "Tools.DotNetBinarySerialize(object data) Binary 序列化错误:" + exp;
                    LogError(logMsg);
                    return null;
                }
            }
        }
        public static object DotNetBinaryDeserialize(byte[] data)
        {
            return DotNetBinaryDeserialize(data, false);
        }
        public static object DotNetBinaryDeserialize(byte[] data, bool throwEeception)
        {
            if (data == null || data.Length <= 0) return null;
            try
            {
                System.Runtime.Serialization.Formatters.Binary.BinaryFormatter formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
                object result = null;
                using (MemoryStream rems = new MemoryStream(data))
                {
                    using (GZipStream zipStream = new GZipStream(rems, CompressionMode.Decompress))
                    {
                        result = formatter.Deserialize(zipStream);
                        zipStream.Close();
                    }
                    return result;
                }
            }
            catch (System.Threading.ThreadAbortException) { throw; }
            catch (Exception exp)
            {
                if (throwEeception) throw;
                else
                {
                    string logMsg = "Tools.DotNetBinaryDeserialize(byte[] data) Binary 反序列化错误:" + exp;
                    LogError(logMsg);
                    return null;
                }
            }
        }


        public static string DotNetXmlSerialize(object data)
        {
            return DotNetXmlSerialize(data, false);
        }
        public static string DotNetXmlSerialize(object data, bool throwEeception)
        {
            if (data == null) return string.Empty;

            try
            {
                StringBuilder stringBuilder = new StringBuilder();
                XmlSerializer xmlSerializer = new XmlSerializer(data.GetType());
                using (TextWriter textWriter = new StringWriter(stringBuilder))
                {
                    xmlSerializer.Serialize(textWriter, data);
                }
                return stringBuilder.ToString();
            }
            catch (System.Threading.ThreadAbortException) { throw; }
            catch (Exception exp)
            {
                if (throwEeception) throw;
                else
                {
                    string logMsg = "Tools.DotNetXmlSerialize(object data) Xml 序列化错误:" + exp;
                    LogError(logMsg);
                    return null;
                }
            }
        }
        public static T DotNetXmlDeserialize<T>(string xml)
        {
            return DotNetXmlDeserialize<T>(xml, false);
        }
        public static T DotNetXmlDeserialize<T>(string xml, bool throwEeception)
        {
            try
            {
                T result;
                StringBuilder stringBuilder = new StringBuilder(xml);
                XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
                using (TextReader textReader = new StringReader(stringBuilder.ToString()))
                {
                    Object record = xmlSerializer.Deserialize(textReader);
                    result = (T)record;
                }
                return result;
            }
            catch (System.Threading.ThreadAbortException) { throw; }
            catch (Exception exp)
            {
                if (throwEeception) throw;
                else
                {
                    string logMsg = "Tools.DotNetXmlDeserialize<T>(string xml) Xml 反序列化错误:" + exp;
                    LogError(logMsg);
                    return default(T);
                }
            }
        }
        public static object DotNetXmlDeserialize(string xml, Type type)
        {
            return DotNetXmlDeserialize(xml, type, false);
        }
        public static object DotNetXmlDeserialize(string xml, Type type, bool throwEeception)
        {
            try
            {
                StringBuilder stringBuilder = new StringBuilder(xml);
                XmlSerializer xmlSerializer = new XmlSerializer(type);
                using (TextReader textReader = new StringReader(stringBuilder.ToString()))
                {
                    Object record = xmlSerializer.Deserialize(textReader);
                    return record;
                }
            }
            catch (System.Threading.ThreadAbortException) { throw; }
            catch (Exception exp)
            {
                if (throwEeception) throw;
                else
                {
                    string logMsg = "Tools.DotNetXmlDeserialize(string xml, Type type) Xml 反序列化错误:" + exp;
                    LogError(logMsg);
                    return null;
                }
            }
        }



        public static string BinaryToBase64(byte[] bytes)
        {
            if (bytes == null || bytes.Length <= 0) return string.Empty;
            try
            {
                string base64 = Convert.ToBase64String(bytes);
                return base64;
            }
            catch (System.Threading.ThreadAbortException) { throw; }
            catch (Exception) { return string.Empty; }
        }
        public static byte[] Base64ToBinary(string base64)
        {
            if (base64 == null || base64.Length <= 0) return null;
            try
            {
                byte[] bytes = Convert.FromBase64String(base64);
                return bytes;
            }
            catch (System.Threading.ThreadAbortException) { throw; }
            catch (Exception) { return null; }
        }
        public static string ObjectToBase64(object record)
        {
            try
            {
                byte[] bytes = DotNetBinarySerialize(record);
                string base64 = Convert.ToBase64String(bytes);
                return base64;
            }
            catch (System.Threading.ThreadAbortException) { throw; }
            catch (Exception) { return string.Empty; }
        }
        public static T ObjectFromBase64<T>(string str64)
        {
            object obj = ObjectFromBase64(str64);
            T record = obj is T ? (T)obj : default(T);
            return record;
        }
        public static object ObjectFromBase64(string str64)
        {
            try
            {
                byte[] bytes = Convert.FromBase64String(str64);
                object obj = DotNetBinaryDeserialize(bytes);
                return obj;
            }
            catch (System.Threading.ThreadAbortException) { throw; }
            catch (Exception) { return null; }
        }

        #endregion


        #region  操 作 字 符 串


        /// <summary>
        /// 格式化一段字符串, 将字符串中的 非预期的 幽灵字符 删除.
        /// <para>本函数将保留 空白符 \r 回车(CR) \n 换行(LF) \t 水平制表(HT) 这几个常用字符</para>
        /// <para>其他未知的 幽灵字符 将直接剔除. 极少使用的 幽灵字符 也会被剔除</para>
        /// </summary>
        public static string FormatString(string str)
        {
            return FormatString(str, false);
        }
        /// <summary>
        /// 格式化一段字符串, 将字符串中的 非预期的 幽灵字符 删除.
        /// <para>本函数将保留 空白符 \r 回车(CR) \n 换行(LF) \t 水平制表(HT) 这几个常用字符</para>
        /// <para>preserveRare 参数决定如下字符是否保留(true: 保留, false 剔除, 默认 false剔除): \a 响铃(BEL) \b 退格(BS) \f 换页(FF) \v 垂直制表(VT) \0 空字符(一般C++标识字符串结束) </para>
        /// <para>其他根本没见过的 幽灵字符 将直接剔除.</para>
        /// </summary>
        public static string FormatString(string str, bool preserveRare)
        {
            if (string.IsNullOrEmpty(str)) return string.Empty;

            StringBuilder sb = new StringBuilder();
            foreach (char c in str)
            {
                if (c == 65279) continue;
                if (c == ' ' || c == '\r' || c == '\n' || c == '\t') { sb.Append(c); continue; }
                if (c == '\a' || c == '\b' || c == '\f' || c == '\v' || c == '\0') { if (preserveRare) { sb.Append(c); } continue; }  //这段代码感觉有性能问题，但细品之下却发现：毫无破绽
                if (!char.IsWhiteSpace(c)) { sb.Append(c); continue; }

                //剩下的 幽灵字符 特殊处理:
                //经过测试: 0x0 - 0xFFFFFF 的 char 字符中, 幽灵字符 要么是 控制符, 要么是分割符.
                //如果是 分隔符, 我们将其替换成空格
                //如果是 控制符, 我们将其直接剔除, 
                if (char.IsSeparator(c)) { sb.Append(' '); continue; }
                //if (char.IsControl(c)) continue; //无意义代码，不需要执行：剩下的字符 通通过滤掉
            }

            return sb.ToString();
        }
        //private const int CHAR_SPACE = (int)' ';
        //private const int CHAR_R = (int)'\r';
        //private const int CHAR_N = (int)'\n';
        //private const int CHAR_T = (int)'\t';
        //private const int CHAR_A = (int)'\a';
        //private const int CHAR_B = (int)'\b';
        //private const int CHAR_F = (int)'\f';
        //private const int CHAR_V = (int)'\v';
        //private const int CHAR_0 = (int)'\0';
        //private static string FormatString(string str, bool preserveRare)
        //{
        //    if (string.IsNullOrEmpty(str)) return string.Empty;

        //    StringBuilder sb = new StringBuilder();
        //    foreach (char c in str)
        //    {
        //        int i = (int)c;
        //        if (i == CHAR_SPACE || i == CHAR_R || i == CHAR_N || i == CHAR_T) { sb.Append(c); continue; }
        //        if (i == CHAR_A || i == CHAR_B || i == CHAR_F || i == CHAR_V || i == CHAR_0) { if (preserveRare) { sb.Append(c); } continue; }
        //        if (!char.IsWhiteSpace(c)) { sb.Append(c); continue; }

        //        //剩下的 不可见字符 特殊处理: 不占用显示位的不可见字符直接剔除, 占用显示位但不可见(或某些时候显示成?)的字符用空格符替换
        //        //鉴于 暂时无法识别: 哪些幺蛾子字符是隐形的 哪些幺蛾子字符是显形的, 因此暂时统一替换成 空格符
        //        sb.Append(' ');
        //    }

        //    return sb.ToString();
        //}


        /// <summary>
        /// 判断字符是否是全角符号
        /// </summary>
        public static bool IsSBC(char ch)
        {
            return ((ch >= 65281 && ch <= 65374) || ch == 12288);
        }



        public static string InsureStartWith(string str, string start)
        {
            return InsureStartWith(str, start, true);
        }
        public static string InsureEndWith(string str, string end)
        {
            return InsureEndWith(str, end, true);
        }
        public static string InsureStartWith(string str, string start, bool ignore)
        {
            //保证字符串 以 指定的字符开头
            string newStr = str.TrimStart();
            bool isStart = ignore
                               ? newStr.StartsWith(start, StringComparison.CurrentCultureIgnoreCase)
                               : newStr.StartsWith(start);
            if (isStart) return str;

            newStr = start + str;
            return newStr;
        }
        public static string InsureEndWith(string str, string end, bool ignore)
        {
            //保证字符串 以 指定的字符皆为
            string newStr = str.TrimEnd();
            bool isEnd = ignore
                               ? newStr.EndsWith(end, StringComparison.CurrentCultureIgnoreCase)
                               : newStr.EndsWith(end);
            if (isEnd) return str;

            newStr = str + end;
            return newStr;
        }

        /// <summary>
        /// 将一个 字符串按照指定的编码 压缩成Zip字节流
        /// </summary>
        public static byte[] EnZipString(string value, Encoding encoding)
        {
            if (value == null) return null;
            if (value.Length <= 0) return new byte[0];

            using (MemoryStream memoryStream = new MemoryStream())
            {
                using (GZipStream zipStream = new GZipStream(memoryStream, CompressionMode.Compress))
                {
                    using (StreamWriter streamWriter = new StreamWriter(zipStream, encoding))
                    {
                        streamWriter.Write(value);
                    }
                    zipStream.Close();
                }

                return memoryStream.ToArray();
            }
        }
        /// <summary>
        /// 将一个 Zip字节流 按照指定编码 还原成 最初的 字符串
        /// </summary>
        public static string UnZipString(byte[] bytes, Encoding encoding)
        {
            if (bytes == null) return null;
            if (bytes.Length <= 0) return string.Empty;

            string result = string.Empty;
            using (MemoryStream memoryStream = new MemoryStream(bytes))
            {
                using (GZipStream zipStream = new GZipStream(memoryStream, CompressionMode.Decompress))
                {
                    using (StreamReader streamReader = new StreamReader(zipStream, encoding))
                    {
                        result = streamReader.ReadToEnd();
                    }
                    zipStream.Close();
                }
            }
            return result;
        }
        /// <summary>
        /// 计算一段 字符串的 MD5 值
        /// </summary>
        public static string GetStringMD5(string str)
        {
            if (string.IsNullOrEmpty(str)) return string.Empty;
            try
            {
                byte[] bytes = Encoding.UTF8.GetBytes(str);

                using (MD5 md5 = new MD5CryptoServiceProvider())
                {
                    md5.Initialize();
                    md5.TransformFinalBlock(bytes, 0, bytes.Length);
                    byte[] hash = md5.Hash;
                    StringBuilder sb = new StringBuilder();
                    for (int i = 0; i < hash.Length; i++) sb.Append(hash[i].ToString("x2"));
                    return sb.ToString();
                }
            }
            catch (System.Threading.ThreadAbortException) { throw; }
            catch (Exception) { return string.Empty; }
        }

        public static bool IsNullOrWhiteSpace(string value)
        {
            if (value == null) return true;
            for (int i = 0; i < value.Length; i++)
                if (!char.IsWhiteSpace(value[i]))
                    return false;
            return true;
        }

        #region  最简平衡组的捕获

        /// <summary>
        /// 计算出一段字符串中
        /// </summary>
        /// <param name="str">需要识别平衡组的字符串</param>
        /// <param name="index">平衡组开始识别的起始位置</param>
        /// <param name="gstart">平衡组的左起始字符, 比如: &lt; { ( [ </param>
        /// <param name="gend">平衡组的右结束字符, 比如: &gt; } ) ] </param>
        /// <returns>平衡组的结束字符所在的索引</returns>
        public static int GStringEndIndexOf(string str, int index, char gstart, char gend)
        {
            if (str[index] != gstart)
                throw new ArgumentException("参数 str 的 index 所在位置的字符 不是平衡组的起始字符!");

            char[] chars = str.ToCharArray();
            int stack = 0;
            for (int i = index, len = chars.Length; i < len; i++)
            {
                char c = chars[i];
                if (c == gstart) stack++;
                else if (c == gend) { stack--; if (stack == 0) return i; }
            }

            return -1;
        }


        #endregion



        //Split 函数 是为 WinCE 平台而写；
        //好吧，我承认 Split 函数，微软的代码 看着 头晕，自己写个，性能肯定是比不上微软了；
        public static string[] Split(string source, string split, StringSplitOptions splitOptions)
        {
            return Split(source, split, splitOptions, StringComparison.CurrentCulture);
        }
        public static string[] Split(string source, string split, StringSplitOptions splitOptions, StringComparison stringComparison)
        {
            if (string.IsNullOrEmpty(source)) return new[] { source ?? string.Empty };
            if (split == null || split.Length <= 0) return new[] { source };

            List<string> items = new List<string>();

            while (source.Length > 0)
            {
                int index = source.IndexOf(split, stringComparison);
                if (index >= 0)
                {
                    string item = index == 0 ? string.Empty : source.Substring(0, index);
                    if (splitOptions != StringSplitOptions.RemoveEmptyEntries || !IsNullOrWhiteSpace(item))
                        items.Add(item);
                    source = source.Substring(index + split.Length);
                }
                else
                {
                    if (splitOptions != StringSplitOptions.RemoveEmptyEntries || !IsNullOrWhiteSpace(source))
                        items.Add(source);
                    source = string.Empty;
                }
            }

            return items.ToArray();
        }
        public static string[] Split(string source, char[] split, StringSplitOptions splitOptions)
        {
            return Split(source, split, splitOptions, StringComparison.CurrentCulture);
        }
        public static string[] Split(string source, char[] split, StringSplitOptions splitOptions, StringComparison stringComparison)
        {
            if (string.IsNullOrEmpty(source)) return new[] { source ?? string.Empty };
            if (split == null || split.Length <= 0) return new[] { source };

            int[] listSplitIndex = GetSplitIndex(source, split, stringComparison);
            if (listSplitIndex == null || listSplitIndex.Length <= 0) return new[] { source };

            bool flag = splitOptions == StringSplitOptions.RemoveEmptyEntries;
            List<string> items = new List<string>();

            //|00|111|
            //01234567
            //0  3   7
            //0  1   2

            int listSplitLength = listSplitIndex.Length;
            int splitIndex = 0;                                     //0     1   2
            int sourceSplitIndex = listSplitIndex[splitIndex];      //0     3   7
            StringBuilder sb = new StringBuilder();
            for (int i = 0, count = source.Length; i < count; i++)  //0 1 2 3 4 5 6 7
            {
                if (i >= sourceSplitIndex)                          //0>=0 | 3>=3 | 7>=7 |
                {
                    string splitItem = sb.ToString();               // | 
                    if (!string.IsNullOrEmpty(splitItem) || (!flag)) items.Add(splitItem);  //TF | T | T

                    if (sb.Length > 0) sb.Remove(0, sb.Length);                             //F  | T 
                    splitIndex++;                                           //1  2  3
                    sourceSplitIndex = listSplitLength > splitIndex ? listSplitIndex[splitIndex] : count + 1;      //3  7  8
                }
                else if (i < sourceSplitIndex)                      //1,2<3 | 4,5,6<7
                {
                    sb.Append(source[i]);                           //00    | 111
                }
            }

            string lastSplitItem = sb.ToString();
            if (!string.IsNullOrEmpty(lastSplitItem) || (!flag)) items.Add(lastSplitItem);

            return items.ToArray();
        }

        private static int[] GetSplitIndex(string source, char[] separator, StringComparison stringComparison)
        {
            List<int> sepList = new List<int>();

            for (int i = 0, count = source.Length; i < count; i++)
            {
                string iString = source[i].ToString();
                for (int j = 0, length = separator.Length; j < length; j++)
                {
                    string jString = separator[j].ToString();
                    if (jString.Equals(iString, stringComparison))
                        sepList.Add(i);
                }
            }

            return sepList.ToArray();
        }


        public static string Join(string separator, params string[] value)
        {
            if (value == null)
            {
                throw new ArgumentNullException("value");
            }
            return string.Join(separator, value, 0, value.Length);
        }
        public static string Join(string separator, params object[] values)
        {
            if (values == null)
            {
                throw new ArgumentNullException("values");
            }
            if (values.Length == 0 || values[0] == null)
            {
                return string.Empty;
            }
            if (separator == null)
            {
                separator = string.Empty;
            }
            StringBuilder stringBuilder = new StringBuilder();
            string text = values[0].ToString();
            if (text != null)
            {
                stringBuilder.Append(text);
            }
            for (int i = 1; i < values.Length; i++)
            {
                stringBuilder.Append(separator);
                if (values[i] != null)
                {
                    text = values[i].ToString();
                    if (text != null)
                    {
                        stringBuilder.Append(text);
                    }
                }
            }
            return stringBuilder.ToString();
        }
        public static string Join<T>(string separator, IEnumerable<T> values)
        {
            if (values == null)
            {
                throw new ArgumentNullException("values");
            }
            if (separator == null)
            {
                separator = string.Empty;
            }
            string result;
            using (IEnumerator<T> enumerator = values.GetEnumerator())
            {
                if (!enumerator.MoveNext())
                {
                    result = string.Empty;
                }
                else
                {
                    StringBuilder stringBuilder = new StringBuilder();
                    if (!Equals(enumerator.Current, default(T)))
                    {
                        T current = enumerator.Current;
                        string text = current.ToString();
                        if (text != null)
                        {
                            stringBuilder.Append(text);
                        }
                    }
                    while (enumerator.MoveNext())
                    {
                        stringBuilder.Append(separator);
                        if (!Equals(enumerator.Current, default(T)))
                        {
                            T current2 = enumerator.Current;
                            string text2 = current2.ToString();
                            if (text2 != null)
                            {
                                stringBuilder.Append(text2);
                            }
                        }
                    }
                    result = stringBuilder.ToString();
                }
            }
            return result;
        }
        public static string Join(string separator, IEnumerable<string> values)
        {
            if (values == null)
            {
                throw new ArgumentNullException("values");
            }
            if (separator == null)
            {
                separator = string.Empty;
            }
            string result;
            using (IEnumerator<string> enumerator = values.GetEnumerator())
            {
                if (!enumerator.MoveNext())
                {
                    result = string.Empty;
                }
                else
                {
                    StringBuilder stringBuilder = new StringBuilder();
                    if (enumerator.Current != null)
                    {
                        stringBuilder.Append(enumerator.Current);
                    }
                    while (enumerator.MoveNext())
                    {
                        stringBuilder.Append(separator);
                        if (enumerator.Current != null)
                        {
                            stringBuilder.Append(enumerator.Current);
                        }
                    }
                    result = stringBuilder.ToString();
                }
            }
            return result;
        }



        #endregion


        #region  类 型 转 换

        /// <summary>
        /// 将一个 Type字符串 转换成 Type
        /// </summary>
        public static Type FromTypeName(string typeName)
        {
            return FromTypeName(typeName, null);
        }
        /// <summary>
        /// 将一个 Type字符串 转换成 Type
        /// </summary>
        public static Type FromTypeName(string typeName, Type defaultValue)
        {
            if (string.IsNullOrEmpty(typeName)) return defaultValue;
            Type type = Type.GetType(typeName);
            return type;
        }
        /// <summary>
        /// 将一个 Type 转换成 Type字符串
        /// </summary>
        public static string ToTypeName(Type type)
        {
            if (type == null) return string.Empty;
            string typeName = type.AssemblyQualifiedName;
            return typeName;
        }





        private static readonly Regex m_RegGenericNum = new Regex(@"(?<=[\w\$])`[\d]+(?=\<)", RegexOptions.IgnoreCase | RegexOptions.Compiled);
        private static readonly Regex m_RegTypeGeneric = new Regex(@"`\d+", RegexOptions.Compiled | RegexOptions.IgnoreCase);

        /// <summary>
        /// 获取 一个类型的 可识别名称 (本名称 只能用来 显示, 不能再反向 得到 Type)
        /// </summary>
        public static string GetKnowTypeName(Type type)
        {
            if (type == null) return string.Empty;

            Type[] genTypes = type.GetGenericArguments();
            string[] listTypeName = new string[genTypes.Length];
            for (int i = 0, count = genTypes.Length; i < count; i++)
                listTypeName[i] = GetKnowTypeName(genTypes[i]);

            string typeName = m_RegTypeGeneric.Replace((!IsNullOrWhiteSpace(type.Name) ? type.Name : type.FullName), "").Replace("+", ".");
            return genTypes.Length > 0 ? string.Format("{0}<{1}>", typeName, string.Join(",", listTypeName)) : typeName;
        }
        /// <summary>
        /// 获取 一个类型的 可识别全名称 (本名称 只能用来 显示, 不能再反向 得到 Type)
        /// </summary>
        public static string GetKnowFullTypeName(Type type)
        {
            if (type == null) return string.Empty;

            Type[] genTypes = type.GetGenericArguments();
            string[] listTypeName = new string[genTypes.Length];
            for (int i = 0, count = genTypes.Length; i < count; i++)
                listTypeName[i] = GetKnowFullTypeName(genTypes[i]);

            string typeName = m_RegTypeGeneric.Replace((!IsNullOrWhiteSpace(type.FullName) ? type.FullName : type.Name), "").Replace("+", ".");
            return genTypes.Length > 0 ? string.Format("{0}<{1}>", typeName, string.Join(",", listTypeName)) : typeName;
        }

        /// <summary>
        /// 获取 一个函数的 可识别定义 (本名称 只能用来 显示, 不能再反向 得到 MethodInfo)
        /// </summary>
        public static string GetKnowMethodDefine(MethodInfo method)
        {
            if (method == null) return string.Empty;

            Type[] genTypes = method.GetGenericArguments();
            string[] listTypeName = new string[genTypes.Length];
            for (int i = 0, count = genTypes.Length; i < count; i++)
                listTypeName[i] = GetKnowTypeName(genTypes[i]);

            ParameterInfo[] mtdParams = method.GetParameters();
            string[] listParamName = new string[mtdParams.Length];
            for (int i = 0, count = mtdParams.Length; i < count; i++)
            {
                string type = GetKnowTypeName(mtdParams[i].ParameterType);
                listParamName[i] = string.Format("{0} {1}", type, mtdParams[i].Name);
            }

            string retTypeName = GetKnowTypeName(method.ReturnType);
            string decTypeName = GetKnowTypeName(method.DeclaringType);
            string @pub = method.IsPrivate ? "private" : (method.IsPublic ? "public" : string.Empty);
            string @sta = method.IsStatic ? " static" : string.Empty;

            string result = genTypes.Length > 0
                       ? string.Format("{6}{5} {4} {3}.{0}<{1}>({2})", method.Name, string.Join(", ", listTypeName), string.Join(", ", listParamName), decTypeName, retTypeName, @sta, @pub)
                       : string.Format("{5}{4} {3} {2}.{0}({1})", method.Name, string.Join(", ", listParamName), decTypeName, retTypeName, @sta, @pub);


            result = m_RegGenericNum.Replace(result, string.Empty);
            return result;
        }



        #endregion
        

        #region  数 据 转 换



        public static byte ToFByte(object obj, string property)
        {
            object value = GetValue(obj, property);
            return ToByte(value);
        }
        public static short ToFShort(object obj, string property)
        {
            object value = GetValue(obj, property);
            return ToShort(value);
        }
        public static int ToFInt(object obj, string property)
        {
            object value = GetValue(obj, property);
            return ToInt(value);
        }
        public static long ToFLong(object obj, string property)
        {
            object value = GetValue(obj, property);
            return ToLong(value);
        }
        public static float ToFFloat(object obj, string property)
        {
            object value = GetValue(obj, property);
            return ToFloat(value);
        }
        public static double ToFDouble(object obj, string property)
        {
            object value = GetValue(obj, property);
            return ToDouble(value);
        }
        public static decimal ToFDecimal(object obj, string property)
        {
            object value = GetValue(obj, property);
            return ToDecimal(value);
        }
        public static string ToFString(object obj, string property)
        {
            object value = GetValue(obj, property);
            return ToString(value);
        }
        public static DateTime ToFDateTime(object obj, string property)
        {
            object value = GetValue(obj, property);
            return ToDateTime(value);
        }
        public static Guid ToFGuid(object obj, string property)
        {
            object value = GetValue(obj, property);
            return ToGuid(value);
        }
        public static bool ToFBoolean(object obj, string property)
        {
            object value = GetValue(obj, property);
            return ToBoolean(value);
        }
        public static char ToFChar(object obj, string property)
        {
            object value = GetValue(obj, property);
            return ToChar(value);
        }

        public static byte ToFByte(object obj, string property, byte @default)
        {
            object value = GetValue(obj, property);
            return ToByte(value, @default);
        }
        public static short ToFShort(object obj, string property, short @default)
        {
            object value = GetValue(obj, property);
            return ToShort(value, @default);
        }
        public static int ToFInt(object obj, string property, int @default)
        {
            object value = GetValue(obj, property);
            return ToInt(value, @default);
        }
        public static long ToFLong(object obj, string property, long @default)
        {
            object value = GetValue(obj, property);
            return ToLong(value, @default);
        }
        public static float ToFFloat(object obj, string property, float @default)
        {
            object value = GetValue(obj, property);
            return ToFloat(value, @default);
        }
        public static double ToFDouble(object obj, string property, double @default)
        {
            object value = GetValue(obj, property);
            return ToDouble(value, @default);
        }
        public static decimal ToFDecimal(object obj, string property, decimal @default)
        {
            object value = GetValue(obj, property);
            return ToDecimal(value, @default);
        }
        public static string ToFString(object obj, string property, string @default)
        {
            object value = GetValue(obj, property);
            return ToString(value, @default);
        }
        public static DateTime ToFDateTime(object obj, string property, DateTime @default)
        {
            object value = GetValue(obj, property);
            return ToDateTime(value, @default);
        }
        public static Guid ToFGuid(object obj, string property, Guid @default)
        {
            object value = GetValue(obj, property);
            return ToGuid(value, @default);
        }
        public static bool ToFBoolean(object obj, string property, bool @default)
        {
            object value = GetValue(obj, property);
            return ToBoolean(value, @default);
        }
        public static char ToFChar(object obj, string property, char @default)
        {
            object value = GetValue(obj, property);
            return ToChar(value, @default);
        }

        private static readonly DateTime m_DefaultTime = new DateTime(1900, 01, 01);

        public static byte ToByte(object obj)
        {
            return ToByte(obj, 0);
        }
        public static short ToShort(object obj)
        {
            return ToShort(obj, 0);
        }
        public static int ToInt(object obj)
        {
            return ToInt(obj, 0);
        }
        public static long ToLong(object obj)
        {
            return ToLong(obj, 0);
        }
        public static float ToFloat(object obj)
        {
            return ToFloat(obj, 0);
        }
        public static double ToDouble(object obj)
        {
            return ToDouble(obj, 0);
        }
        public static decimal ToDecimal(object obj)
        {
            return ToDecimal(obj, 0);
        }
        public static string ToString(object obj)
        {
            return ToString(obj, string.Empty);
        }
        public static DateTime ToDateTime(object obj)
        {
            return ToDateTime(obj, m_DefaultTime);
        }
        public static Guid ToGuid(object obj)
        {
            return ToGuid(obj, Guid.Empty);
        }
        public static bool ToBoolean(object obj)
        {
            return ToBoolean(obj, false);
        }
        public static char ToChar(object obj)
        {
            return ToChar(obj, char.MinValue);
        }

        public static byte ToByte(object obj, byte @default)
        {
            if (obj == null) return @default;
            if (obj is byte) return (byte)obj;
#if (!WindowsCE && !PocketPC)
            string str = obj.ToString().Trim();
            if (str.StartsWith("0x", StringComparison.CurrentCultureIgnoreCase))
            {
                //16进制
                str = str.Substring(2);
                byte temp;
                if (byte.TryParse(str, System.Globalization.NumberStyles.HexNumber, null, out temp))
                    return temp;
                else return @default;
            }
            else
            {
                double temp;
                if (double.TryParse(str, out temp))
                    return (byte)temp;
                else return @default;
            }
#endif
#if (WindowsCE || PocketPC)
            try { return Convert.ToByte(obj); }
            catch (System.Threading.ThreadAbortException) { throw; }
            catch { return @default; }
#endif
        }
        public static short ToShort(object obj, short @default)
        {
            if (obj == null) return @default;
            if (obj is short) return (short)obj;
#if (!WindowsCE && !PocketPC)
            string str = obj.ToString().Trim();
            if (str.StartsWith("0x", StringComparison.CurrentCultureIgnoreCase))
            {
                //16进制
                str = str.Substring(2);
                short temp;
                if (short.TryParse(str, System.Globalization.NumberStyles.HexNumber, null, out temp))
                    return temp;
                else return @default;
            }
            else
            {
                double temp;
                if (double.TryParse(str, out temp))
                    return (short)temp;
                else return @default;
            }
#endif
#if (WindowsCE || PocketPC)
            try { return (short)Convert.ToDouble(obj); }
            catch (System.Threading.ThreadAbortException) { throw; }
            catch { return @default; }
#endif
        }
        public static int ToInt(object obj, int @default)
        {
            if (obj == null) return @default;
            if (obj is int) return (int)obj;
#if (!WindowsCE && !PocketPC)
            string str = obj.ToString().Trim();
            if (str.StartsWith("0x", StringComparison.CurrentCultureIgnoreCase))
            {
                //16进制
                str = str.Substring(2);
                int temp;
                if (int.TryParse(str, System.Globalization.NumberStyles.HexNumber, null, out temp))
                    return temp;
                else return @default;
            }
            else
            {
                double temp;
                if (double.TryParse(str, out temp))
                    return (int)temp;
                else return @default;
            }
#endif
#if (WindowsCE || PocketPC)
            try { return (int)Convert.ToDouble(obj); }
            catch (System.Threading.ThreadAbortException) { throw; }
            catch { return @default; }
#endif
        }
        public static long ToLong(object obj, long @default)
        {
            if (obj == null) return @default;
            if (obj is long) return (long)obj;

#if (!WindowsCE && !PocketPC)
            string str = obj.ToString().Trim();
            if (str.StartsWith("0x", StringComparison.CurrentCultureIgnoreCase))
            {
                //16进制
                str = str.Substring(2);
                long temp;
                if (long.TryParse(str, System.Globalization.NumberStyles.HexNumber, null, out temp))
                    return temp;
                else return @default;
            }
            else
            {
                double temp;
                if (double.TryParse(str, out temp))
                    return (long)temp;
                else return @default;
            }
#endif
#if (WindowsCE || PocketPC)
            try { return (long)Convert.ToDouble(obj); }
            catch (System.Threading.ThreadAbortException) { throw; }
            catch { return @default; }
#endif
        }
        public static float ToFloat(object obj, float @default)
        {
            if (obj == null) return @default;
            if (obj is float) return (float)obj;
#if (!WindowsCE && !PocketPC)
            double temp;
            if (double.TryParse(obj.ToString(), out temp))
                return (float)temp;
            else return @default;
#endif
#if (WindowsCE || PocketPC)
            try { return (float)Convert.ToDouble(obj); }
            catch (System.Threading.ThreadAbortException) { throw; }
            catch { return @default; }
#endif
        }
        public static double ToDouble(object obj, double @default)
        {
            if (obj == null) return @default;
            if (obj is double) return (double)obj;
#if (!WindowsCE && !PocketPC)
            double temp;
            if (double.TryParse(obj.ToString(), out temp))
                return temp;
            else return @default;
#endif
#if (WindowsCE || PocketPC)
            try { return Convert.ToDouble(obj); }
            catch (System.Threading.ThreadAbortException) { throw; }
            catch { return @default; }
#endif
        }
        public static decimal ToDecimal(object obj, decimal @default)
        {
            if (obj == null) return @default;
            if (obj is decimal) return (decimal)obj;
#if (!WindowsCE && !PocketPC)
            decimal temp;
            if (decimal.TryParse(obj.ToString(), out temp))
                return temp;

            temp = CNNumToDecimal(obj, decimal.MinValue);
            if (temp != decimal.MinValue) return temp;

            return @default;
#endif
#if (WindowsCE || PocketPC)
            try { return Convert.ToDecimal(obj); }
            catch (System.Threading.ThreadAbortException) { throw; }
            catch {
                temp = CNNumToDecimal(obj, decimal.MinValue);
                if (temp != decimal.MinValue) return temp;
                return @default; 
            }
#endif
        }
        public static string ToString(object obj, string @default)
        {
            if (obj == null) return @default;
            if (obj is string) return (string)obj;
            return obj.ToString();
        }
        public static DateTime ToDateTime(object obj, DateTime @default)
        {
            if (obj == null) return @default;
            if (obj is DateTime) return (DateTime)obj;
#if (!WindowsCE && !PocketPC)
            DateTime temp;
            if (DateTime.TryParse(obj.ToString(), out temp))
                if (temp.Year >= 1800 && temp.Year <= 2200) return temp; //在 temp 基本有效时, 直接返回. 否则尝试使用 ParseDate 再试一次且优先返回temp2.

            DateTime temp2 = ParseDate(obj.ToString());
            if (temp2 != DateTime.MinValue) return temp2;
            if (temp != DateTime.MinValue) return temp;
            return @default;
#endif
#if (WindowsCE || PocketPC)
            DateTime temp;
            try { temp = Convert.ToDateTime(obj); } catch (System.Threading.ThreadAbortException) { throw; } catch (Exception ex) { Tools.LogWarn(ex); }
            if (temp.Year >= 1800 && temp.Year <= 2200) return temp; //在 temp 基本有效时, 直接返回. 否则尝试使用 ParseDate 再试一次且优先返回temp2.

            DateTime temp2 = ParseDate(obj.ToString());
            if (temp2 != DateTime.MinValue) return temp2;
            if (temp != DateTime.MinValue) return temp;
            return @default;
#endif
        }
        public static Guid ToGuid(object obj, Guid @default)
        {
            if (obj == null) return @default;
            if (obj is Guid) return (Guid)obj;
            try { return new Guid(obj.ToString()); }
            catch (System.Threading.ThreadAbortException) { throw; }
            catch { return @default; }
        }
        public static bool ToBoolean(object obj, bool @default)
        {
            if (obj == null) return @default;
            if (obj is bool) return (bool)obj;
            if (obj is byte) return (byte)obj > 0;
            if (obj is short) return (short)obj > 0;
            if (obj is int) return (int)obj > 0;
            if (obj is long) return (long)obj > 0;
            if (obj is double) return (double)obj > 0;
            if (obj is float) return (float)obj > 0;
            if (obj is decimal) return (decimal)obj > 0;
            if (string.Equals(obj.ToString(), "T", StringComparison.CurrentCultureIgnoreCase)) return true;

#if (!WindowsCE && !PocketPC)
            bool temp;
            if (bool.TryParse(obj.ToString(), out temp)) return temp;
#endif
#if (WindowsCE || PocketPC)
            try { return Convert.ToBoolean(obj); }
            catch (System.Threading.ThreadAbortException) { throw; }
            catch (Exception ex) { Tools.LogWarn(ex); }
#endif

            double number = ToDouble(obj, double.MinValue);
            if (number > 0) return true;

            return false;
        }
        public static char ToChar(object obj, char @default)
        {
            if (obj == null) return @default;
            if (obj is char) return (char)obj;
#if (!WindowsCE && !PocketPC)
            char temp;
            if (char.TryParse(obj.ToString(), out temp))
                return temp;
            else return @default;
#endif
#if (WindowsCE || PocketPC)
            try { return Convert.ToChar(obj); }
            catch (System.Threading.ThreadAbortException) { throw; }
            catch { return @default; }
#endif
        }


        public static E ToEnum<E>(object obj) where E : struct
        {
            try
            {
                string strValue = (obj ?? string.Empty).ToString().Trim();
                object result = Enum.Parse(typeof(E), strValue, true);
                return (E)result;
            }
            catch (System.Threading.ThreadAbortException) { throw; }
            catch (Exception) { return default(E); }
        }
        public static object ToEnum(Type enumType, object obj)
        {
            try
            {
                string strValue = (obj ?? string.Empty).ToString().Trim();
                object result = Enum.Parse(enumType, strValue, true);
                return result;
            }
            catch (System.Threading.ThreadAbortException) { throw; }
            catch (Exception) { return DefaultForType(enumType); }
        }


        #region  中文数值转换函数

        private static readonly Regex m_RegNoNegNumAndDot = new Regex(@"[^\d\.\-]", RegexOptions.IgnoreCase | RegexOptions.Compiled);
        private static readonly Regex m_RegNoNum = new Regex(@"[^\d]", RegexOptions.IgnoreCase | RegexOptions.Compiled);
        private static readonly Regex m_RegNoNumAndQBS = new Regex(@"[^\d千百十]", RegexOptions.IgnoreCase | RegexOptions.Compiled);
        private static readonly Regex m_RegNoNumAndWYQBS = new Regex(@"[^\d万亿千百十]", RegexOptions.IgnoreCase | RegexOptions.Compiled);

        /// <summary>
        /// 将一段 中文数字 转为 数值类型, 转换失败时 默认返回 0. (使用 Tools.ToDecimal(*) 将达到同样的效果) 
        /// </summary>
        public static decimal CNNumToDecimal(object value)
        {
            return CNNumToDecimal(value, 0);
        }
        /// <summary>
        /// 将一段 中文数字 转为 数值类型 (使用 Tools.ToDecimal(*) 将达到同样的效果)
        /// </summary>
        public static decimal CNNumToDecimal(object value, decimal @default)
        {
            try
            {
                //先尝试 直接转换数据
                decimal result = FormatNumeric(value);
                if (result != decimal.MinValue) return result;

                //再尝试 通过中文转换
                string str = value.ToString();
                str = str.Replace("億", "亿").Replace("萬", "万").Replace("點", "点").Replace("負", "负")
                    .Replace("亿", "亿").Replace("万", "万").Replace("仟", "千").Replace("佰", "百").Replace("拾", "十")
                    .Replace("零", "零").Replace("壹", "一").Replace("贰", "二").Replace("叁", "三").Replace("肆", "四")
                    .Replace("伍", "五").Replace("陆", "六").Replace("柒", "七").Replace("捌", "八").Replace("玖", "九")
                    .Replace("元", "点").Replace("角", string.Empty).Replace("分", string.Empty).Replace("厘", string.Empty).Replace("毫", string.Empty)
                    .Replace("．", ".").Replace("－", "-")
                    .Replace("负", "-").Replace("点", ".")
                    .Replace("１", "1").Replace("２", "2").Replace("３", "3").Replace("４", "4").Replace("５", "5")
                    .Replace("６", "6").Replace("７", "7").Replace("８", "8").Replace("９", "9").Replace("０", "0")
                    .Replace("零", "0").Replace("一", "1").Replace("二", "2").Replace("三", "3").Replace("四", "4")
                    .Replace("五", "5").Replace("六", "6").Replace("七", "7").Replace("八", "8").Replace("九", "9")
                    .Trim();

                bool isNeg = str.StartsWith("-");
                str = str.Replace("-", string.Empty);
                if (str.StartsWith("十")) str = "1" + str;

                string str0 = string.Empty, str1 = string.Empty;
                int id = str.IndexOf(".");
                if (id >= 0) { str0 = str.Substring(0, id); str1 = str.Substring(id + 1); }
                else str0 = str;

                string syy = string.Empty, swy = string.Empty, sy = string.Empty, sw = string.Empty, so = string.Empty;

                //拆分出几个主节点
                str0 = m_RegNoNumAndWYQBS.Replace(str0, string.Empty).Trim();
                int iyy = str0.IndexOf("亿亿");
                if (iyy >= 0) { syy = str0.Substring(0, iyy); str0 = str0.Substring(iyy + 2); }
                int iwy = str0.IndexOf("万亿");
                if (iwy >= 0) { swy = str0.Substring(0, iwy); str0 = str0.Substring(iwy + 2); }
                int iy = str0.IndexOf("亿");
                if (iy >= 0) { sy = str0.Substring(0, iy); str0 = str0.Substring(iy + 1); }
                int iw = str0.IndexOf("万");
                if (iw >= 0) { sw = str0.Substring(0, iw); str0 = str0.Substring(iw + 1); }
                so = str0;

                if (string.IsNullOrEmpty(syy) && string.IsNullOrEmpty(swy) && string.IsNullOrEmpty(sy) && string.IsNullOrEmpty(sw) && string.IsNullOrEmpty(so))
                    return @default;

                long yy = ParseCHSNumToLong(syy);
                long wy = ParseCHSNumToLong(swy);
                long y = ParseCHSNumToLong(sy);
                long w = ParseCHSNumToLong(sw);
                long o = ParseCHSNumToLong(so);

                long num0 = 0
                            + 10000000000000000 * yy
                            + 1000000000000 * wy
                            + 100000000 * y
                            + 10000 * w
                            + o;

                long num1 = ParseCHSNumToLong2(str1);
                decimal num2 = ToDecimal("0." + num1);

                decimal result3 = num0 + num2;
                return isNeg ? 0 - result3 : result3;
            }
            catch (System.Threading.ThreadAbortException) { throw; }
            catch (Exception) { return @default; }
        }
        /// <summary>
        /// 将一个数值类型 转换成 简体中文的金额 (默认 精确到分, 小数点后2位)
        /// </summary>
        public static string ToCHSMoney(object value)
        {
            return ToCHSMoney(value, 2);
        }
        /// <summary>
        /// 将一个数值类型 转换成 繁体中文的金额 (默认 精确到分, 小数点后2位)
        /// </summary>
        public static string ToCHTMoney(object value)
        {
            return ToCHTMoney(value, 2);
        }
        /// <summary>
        /// 将一个数值类型 转换成 简体中文的金额 (小数点后 scale 位, scale 最大为 4)
        /// </summary>
        public static string ToCHSMoney(object value, int scale)
        {
            scale = Math.Max(0, Math.Min(4, scale));
            decimal num = CNNumToDecimal(value, decimal.MinValue);
            if (num == decimal.MinValue) return string.Empty;
            bool isNeg = num < 0;
            num = Math.Round(Math.Abs(num), scale);


            //拆分出 整数部分 和 小数部分
            long num0 = (long)num;
            long num1 = ToLong(Math.Abs(((decimal)num - (decimal)num0)) < (decimal)0.00000000001 ? "0" : ((decimal)num - (decimal)num0).ToString().Split(new[] { '.' })[1]); //这里的 decimal 不能替换成 double 或 float

            string str0 = ParseLongToCHSNum(num0);
            StringBuilder sb = new StringBuilder();
            if (num1 != 0)
            {
                string snum1 = num1.ToString().Trim();
                if ((snum1.Length > scale)) snum1 = snum1.Substring(0, scale);
                for (int i = 0, len = snum1.Length; i < len; i++)
                {
                    sb.Append(ParseCharNumToCHSNum(snum1[i]));
                    if (i == 0) sb.Append("角");
                    if (i == 1) sb.Append("分");
                    if (i == 2) sb.Append("厘");
                    if (i == 3) sb.Append("毫");
                }
            }
            string str1 = sb.ToString();

            string result = str0 + "元" + str1;
            if (isNeg) result = "负" + result;
            result = CHSNumToCHSMoney(result);
            return result;
        }
        /// <summary>
        /// 将一个数值类型 转换成 繁体中文的金额 (小数点后 scale 位, scale 最大为 4)
        /// </summary>
        public static string ToCHTMoney(object value, int scale)
        {
            string numCHS = ToCHSMoney(value, scale);
            string numCHT = numCHS.Replace("亿", "億").Replace("万", "萬").Replace("点", "點").Replace("负", "負");
            return numCHT;
        }
        /// <summary>
        /// 将一个数值类型 转换成 简体中文 (默认 精确到 小数点后8位)
        /// </summary>
        public static string ToCHSNumeric(object value)
        {
            return ToCHSNumeric(value, 8);
        }
        /// <summary>
        /// 将一个数值类型 转换成 繁体中文 (默认 精确到 小数点后8位)
        /// </summary>
        public static string ToCHTNumeric(object value)
        {
            return ToCHSNumeric(value, 8);
        }
        /// <summary>
        /// 将一个数值类型 转换成 简体中文 (小数点后 scale 位, scale 最大为 8)
        /// </summary>
        public static string ToCHSNumeric(object value, int scale)
        {
            scale = Math.Max(0, Math.Min(8, scale));
            decimal num = CNNumToDecimal(value, decimal.MinValue);
            if (num == decimal.MinValue) return string.Empty;
            bool isNeg = num < 0;
            num = Math.Round(Math.Abs(num), scale);


            //拆分出 整数部分 和 小数部分
            long num0 = (long)num;
            long num1 = ToLong(Math.Abs(((decimal)num - (decimal)num0)) < (decimal)0.00000000001 ? "0" : ((decimal)num - (decimal)num0).ToString().Split(new[] { '.' })[1]); //这里的 decimal 不能替换成 double 或 float
            string snum1 = num1.ToString().Trim();
            if ((snum1.Length > scale)) num1 = ToLong(snum1.Substring(0, scale));

            string str0 = ParseLongToCHSNum(num0);
            string str1 = ParseLongToCHSNum2(num1).TrimEnd('零');
            string result = (string.IsNullOrEmpty(str1)) ? str0 : str0 + "点" + str1;

            if (result.StartsWith("一十")) result = result.Substring(1);
            if (isNeg) result = "负" + result;
            return result;
        }
        /// <summary>
        /// 将一个数值类型 转换成 繁体中文 (小数点后 scale 位, scale 最大为 4)
        /// </summary>
        public static string ToCHTNumeric(object value, int scale)
        {
            string numCHS = ToCHSNumeric(value, scale);
            string numCHT = numCHS.Replace("亿", "億").Replace("万", "萬").Replace("点", "點").Replace("负", "負");
            return numCHT;
        }
        /// <summary>
        /// <para>将一个 中文数字字符表述的数字 替换成 金额字符表述的数字</para>
        /// <para>比如: "一百二十三" 会被替换成 "壹佰贰拾叁"</para>
        /// </summary>
        public static string CHSNumToCHSMoney(string chs)
        {
            chs = (chs ?? string.Empty).Trim();
            if (string.IsNullOrEmpty(chs)) return string.Empty;

            //string str1 = "零壹贰叁肆伍陆柒捌玖";            //0-9所对应的汉字 
            //string str2 = "万仟佰拾亿仟佰拾万仟佰拾元角分"; //数字位所对应的汉字 

            string money = chs.Replace("亿", "亿").Replace("万", "万").Replace("千", "仟").Replace("百", "佰").Replace("十", "拾")
                .Replace("零", "零").Replace("一", "壹").Replace("二", "贰").Replace("三", "叁").Replace("四", "肆")
                .Replace("五", "伍").Replace("六", "陆").Replace("七", "柒").Replace("八", "捌").Replace("九", "玖");
            return money;
        }


        private static decimal FormatNumeric(object value)
        {
            try
            {
                string str = value.ToString().Trim().Replace("．", ".").Replace("－", "-")
                    .Replace("１", "1").Replace("２", "2").Replace("３", "3").Replace("４", "4").Replace("５", "5")
                    .Replace("６", "6").Replace("７", "7").Replace("８", "8").Replace("９", "9").Replace("０", "0");
                str = m_RegNoNegNumAndDot.Replace(str, string.Empty); //删除 01234567890. 之外的字符
                bool isNeg = str.StartsWith("-");
                str = str.Replace("-", string.Empty);

                decimal result = decimal.MinValue;

                decimal temp0;
                if (!decimal.TryParse(str, out temp0)) temp0 = decimal.MinValue;

                if (temp0 != decimal.MinValue) result = temp0;
                else
                {
                    double temp1 = ToDouble(str, double.MinValue);
                    if (Math.Abs(temp1 - double.MinValue) >= 0.1) result = (decimal)temp1;
                }

                if (result == decimal.MinValue) return decimal.MinValue;
                return isNeg ? 0 - result : result;
            }
            catch (System.Threading.ThreadAbortException) { throw; }
            catch (Exception) { return decimal.MinValue; }
        }
        private static string ParseLongToCHSNum(long value)
        {
            if (value == 0) return "零";
            string vs = value.ToString();

            const string cxtNum = "0123456789";
            const string cxtStr = "零一二三四五六七八九";
            string[] arrPart0 = { "", "万", "亿", "万亿", "亿亿" };   //节权位
            string[] arrPart1 = { "", "十", "百", "千" };            //权位

            StringBuilder sb = new StringBuilder();
            string p = string.Empty;
            for (int i = 0, len = vs.Length; i < len; i++)
            {
                int p0 = (int)Math.Floor((double)(len - i - 1) / (double)4);    //(10-1)/4 = 2.25 = 2 亿    //(8-1)/4 = 1.75 = 1 万 
                int p1 = (len - i - 1) % 4;                                     //(10-1)%4 = 1 十    //(8-1)%4 = 3 千
                string sp0 = arrPart0[p0];
                string sp1 = arrPart1[p1];

                char num = vs[i];
                char str = cxtStr[cxtNum.IndexOf(num)];
                if (str != '零') p = p + str + sp1;
                else if (!p.EndsWith("零")) p = p + str;

                if (p1 == 0)
                {
                    p = p.TrimEnd('零');
                    if (string.IsNullOrEmpty(p)) sb.Append("零");
                    else sb.Append(p + sp0);
                    p = string.Empty;
                }
            }

            string result = sb.ToString();
            if (string.Equals(result, "零", StringComparison.CurrentCultureIgnoreCase)) return result;
            return result.Trim().TrimEnd('零').Trim();
        }
        private static string ParseLongToCHSNum2(long value)
        {
            string str0 = value.ToString();

            const string cxtNum = "0123456789";
            const string cxtStr = "零一二三四五六七八九";

            StringBuilder sb = new StringBuilder();
            for (int i = 0, len = str0.Length; i < len; i++)
            {
                char numStr = str0[i];
                char numCHSStr = cxtStr[cxtNum.IndexOf(numStr)];
                sb.Append(numCHSStr);
            }
            string result = sb.ToString();
            result = result.Trim('零');
            return result;
        }
        private static char ParseCharNumToCHSNum(char value)
        {
            string str0 = value.ToString();
            const string cxtNum = "0123456789";
            const string cxtStr = "零一二三四五六七八九";
            char numStr = str0[0];
            char numCHSStr = cxtStr[cxtNum.IndexOf(numStr)];
            return numCHSStr;
        }
        private static long ParseCHSNumToLong(string chs)
        {
            string str = chs;
            str = m_RegNoNumAndQBS.Replace(str, string.Empty).Trim();

            string sq = string.Empty, sb = string.Empty, ss = string.Empty, sg = string.Empty;
            int @iq = str.IndexOf("千");
            if (@iq >= 0) { sq = str.Substring(0, @iq); str = str.Substring(@iq + 1); }
            int @ib = str.IndexOf("百");
            if (@ib >= 0) { sb = str.Substring(0, @ib); str = str.Substring(@ib + 1); }
            int @is = str.IndexOf("十");
            if (@is >= 0) { ss = str.Substring(0, @is); str = str.Substring(@is + 1); }
            sg = str;

            long num = 0
                        + 1000 * ToLong(sq)
                        + 100 * ToLong(sb)
                        + 10 * ToLong(ss)
                        + ToLong(sg);
            return num;
        }
        private static long ParseCHSNumToLong2(string chs)
        {
            string str = chs;
            str = m_RegNoNum.Replace(str, string.Empty).Trim();
            long num = ToLong(str);
            return num;
        }


        #endregion


        #region  万能时间格式转换函数

        /*本函数 从 inkfx.html5.js 移植而来*/
        /*感谢 InkFx http://www.ink-fx.com 为 ParseDate(dateStr) 函数, 付出的努力 */

        /*将一个 字符串 转换成 时间对象, 转换失败将返回 DateTime.MinValue.本函数会尝试解析 各种时间格式, 因此性能不是那么高. (C) InkFx */
        internal static DateTime ParseDate(string dateStr)
        {
            try
            {
                dateStr = (dateStr ?? string.Empty).Trim();
                if (string.IsNullOrEmpty(dateStr)) return DateTime.MinValue;

                DateTime date;

                /*数值转日期 (只识别 1900-2100范围内的时间)*/
                long dateLong = ToLong(dateStr, long.MinValue);
                if (dateLong != long.MinValue)
                {
                    date = new DateTime(0001, 01, 01, 0, 0, 0, DateTimeKind.Local).AddMilliseconds((double)dateLong / 10000);
                    if (date.Year >= 1900 && date.Year <= 2100) return date; /*C# 的 long>DateTime*/

                    date = new DateTime(1970, 01, 01, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds(dateLong).ToLocalTime();
                    if (date.Year >= 1900 && date.Year <= 2100) return date; /*js 的 number>Date*/
                }

                string str = dateStr.ToUpper();
                if (str.IndexOf("/") >= 0) str = str.Replace("/", "-");             /*将 / 替换成 -    //"yyyy/MM/dd HH:mm:ss.ffffff"*/
                if (str.IndexOf("T") >= 0) str = m_ParseDate_T.Replace(str, " ");   /*将 T 替换成 " "  /*"yyyy-MM-ddTHH:mm:ss.ffffff"*/
                if (str.IndexOf("年") >= 0) str = str.Replace("年", "-");
                if (str.IndexOf("月") >= 0) str = str.Replace("月", "-");
                if (str.IndexOf("日") >= 0) str = str.Replace("日", " ");
                if (str.IndexOf("时") >= 0) str = str.Replace("时", ":");
                if (str.IndexOf("分") >= 0) str = str.Replace("分", ":");
                if (str.IndexOf("秒") >= 0) str = str.Replace("秒", " ");

                str = m_ParseDate_Time.Replace(str, m => string.Format(" {0} ", m.Value));
                str = m_ParseDate_Date.Replace(str, m => string.Format(" {0} ", m.Value));
                str = str.Trim();

                date = ParseDatePD(str);
                if (date != DateTime.MinValue) return date;
                return DateTime.MinValue;
            }
            catch (System.Threading.ThreadAbortException) { throw; }
            catch (Exception) { return DateTime.MinValue; }
        }
        /*按照 指定格式, 将一个 字符串 转换成 时间对象.本函数性能为 5~7W/s (C) InkFx */
        private static DateTime ParseDateF(string dateStr, string dateFormat)
        {
            dateStr = (dateStr ?? string.Empty).Trim();
            if (string.IsNullOrEmpty(dateStr)) return DateTime.MinValue;
            ParseDateV t = new ParseDateV();

            dateStr = dateStr.Trim().ToUpper();
            if (dateStr.IndexOf("/") >= 0) dateStr = dateStr.Replace("/", "-");             /*将 / 替换成 -    //"yyyy/MM/dd HH:mm:ss.ffffff" */
            if (dateStr.IndexOf("T") >= 0) dateStr = m_ParseDate_T.Replace(dateStr, " ");   /*将 T 替换成 " "  //"yyyy-MM-ddTHH:mm:ss.ffffff" */
            if (dateStr.IndexOf("年") >= 0) dateStr = dateStr.Replace("年", "-");
            if (dateStr.IndexOf("月") >= 0) dateStr = dateStr.Replace("月", "-");
            if (dateStr.IndexOf("日") >= 0) dateStr = dateStr.Replace("日", " ");
            if (dateStr.IndexOf("时") >= 0) dateStr = dateStr.Replace("时", ":");
            if (dateStr.IndexOf("分") >= 0) dateStr = dateStr.Replace("分", ":");
            if (dateStr.IndexOf("秒") >= 0) dateStr = dateStr.Replace("秒", " ");
            if (dateFormat.IndexOf("/") >= 0) dateFormat = dateFormat.Replace("/", "-");
            if (dateFormat.IndexOf("T") >= 0) dateFormat = m_ParseDate_T.Replace(dateFormat, " ");
            if (dateFormat.IndexOf("年") >= 0) dateFormat = dateFormat.Replace("年", "-");
            if (dateFormat.IndexOf("月") >= 0) dateFormat = dateFormat.Replace("月", "-");
            if (dateFormat.IndexOf("日") >= 0) dateFormat = dateFormat.Replace("日", " ");
            if (dateFormat.IndexOf("时") >= 0) dateFormat = dateFormat.Replace("时", ":");
            if (dateFormat.IndexOf("分") >= 0) dateFormat = dateFormat.Replace("分", ":");
            if (dateFormat.IndexOf("秒") >= 0) dateFormat = dateFormat.Replace("秒", " ");

            /*替换英文格式的 月份*/
            /*删除英文格式的 星期*/
            /*类似格式(Chrome默认输出格式): Mon Mar 20 2017 02:46:06 GMT+0800 (中国标准时间)*/
            /*类似格式(IE9默认输出格式): Mon Mar 20 02:46:06 UTC+0800 2017*/
            if (dateStr.IndexOf("(") >= 0) dateStr = m_ParseDate_P.Replace(dateStr, string.Empty);
            if (m_ParseDate_AZ.IsMatch(dateStr))
            {
                dateStr = dateStr.Replace("JAN", "1").Replace("FEB", "2").Replace("MAR", "3").Replace("APR", "4").Replace("MAY", "5").Replace("JUN", "6").Replace("JUL", "7").Replace("AUG", "8").Replace("SEP", "9").Replace("OCT", "10").Replace("NOV", "11").Replace("DEC", "12");
                dateStr = dateStr.Replace("SUN", "").Replace("MON", "").Replace("TUE", "").Replace("WED", "").Replace("THU", "").Replace("FRI", "").Replace("SAT", "").Replace("SUNDAY", "").Replace("MONDAY", "").Replace("TUESDAY", "").Replace("WEDNESDAY", "").Replace("THURSDAY", "").Replace("FRIDAY", "").Replace("SATURDAY", "");
                dateStr = m_ParseDate_GU.Replace(dateStr, ""); /*去掉 GMT+0800 UTC+0800 +0800 +08 的时区内容*/
            }

            /*去掉多余空格*/
            dateStr = m_ParseDate_S.Replace(dateStr, " ").Trim();
            dateFormat = m_ParseDate_S.Replace(dateFormat, " ").Trim();
            dateStr = m_ParseDate_SP.Replace(dateStr, m => m.Value.Trim()).Trim();
            dateFormat = m_ParseDate_SP.Replace(dateFormat, m => m.Value.Trim()).Trim();
            bool failed = false;


            ParseDateD d = new ParseDateD();
            m_ParseDate_N.Replace(dateStr, m =>
            {
                if (failed) return string.Empty;

                int i = m.Index;
                string e = m.Value;
                d.v = dateStr.Substring(d.idxV, i - d.idxV);
                d.idxV = i + e.Length;
                int idxF2 = dateFormat.IndexOf(e, d.idxF);
                if (idxF2 >= 0)
                {
                    d.f = dateFormat.Substring(d.idxF, idxF2 - d.idxF);
                    d.idxF = idxF2 + e.Length;
                    ParseDateSV(d.f, d.v, t);
                    d.cntFV = d.cntFV + 1;
                }
                else
                    failed = true;
                return string.Empty;
            });
            if (failed) return DateTime.MinValue;
            if (d.idxV < dateStr.Length - 1 && d.idxF < dateFormat.Length - 1)
            {
                d.v = dateStr.Substring(d.idxV);
                d.f = dateFormat.Substring(d.idxF);
                ParseDateSV(d.f, d.v, t);
                d.cntFV++;
            }

            /*最后书写格式调整*/
            if (d.cntFV == 2)
            {
                /*yyyy-MM 和 MM-dd, 区分这两个模式*/
                if (t.Y < 1000) { t.d = t.M; t.M = t.Y; t.Y = 1900; }
            }
            else
            {
                /*美国人的书写习惯是月/日/年，学校通常使用mm/dd/yyyy来表示，千万不要和英国dd/mm/yyyy(日/月/年)的书写习惯搞混*/
                /*mm/dd/yyyy dd/mm/yyyy 会被替换成 mm-dd-yyyy dd-mm-yyyy*/
                /*yyyy-MM-dd MM-dd-yyyy dd-MM-yyyy, 区分这三个模式*/
                if (t.d >= 1000) { var temp = t.M; t.M = t.Y; t.Y = t.d; t.d = temp; }
                /*dd MM yyyy 交换位置 (yyyy-MM-dd MM-dd-yyyy)*/
                if (t.M >= 13) { var temp2 = t.M; t.M = t.d; t.d = temp2; }
                /*dd 和 MM 交换位置 (如果 yyyy-AA-BB 中, AA<=12, 默认为AA为MM)*/
            }

            while (t.S > 1000) { t.S = t.S / 1000; } /*毫秒值如果超过 1000, 则认定为微妙、纳秒模式*/

            DateTime date = new DateTime(t.Y, t.M, t.d, t.H, t.N, t.s, t.S);
            return date;
        }
        /*判断 指定字符串 中的 指定字符 是否等于 指定数目*/
        private static bool ParseDateCT(string str2, string s1, int n)
        {
            if (string.IsNullOrEmpty(str2)) return false;
            var idx = str2.IndexOf(s1);
            var cnt = 0;
            while (idx >= 0)
            {
                cnt++;
                idx = str2.IndexOf(s1, idx + s1.Length);
            }
            if (cnt == n) return true;
            return false;
        }
        /*将一个 字符串 尝试各种格式 试图转换成 DateTime 类型*/
        private static DateTime ParseDatePD(string dateStr)
        {
            DateTime dt = DateTime.MinValue;

            dateStr = dateStr.Trim();
            if (ParseDateCT(dateStr, "-", 2))
            {
                if (dt == DateTime.MinValue && ParseDateCT(dateStr, ".", 1))
                {
                    if (dt == DateTime.MinValue) dt = ParseDateF(dateStr, "yyyy-MM-dd HH:mm:ss.ffffff");
                }
                else if (dt == DateTime.MinValue && ParseDateCT(dateStr, ":", 2))
                {
                    if (dt == DateTime.MinValue) dt = ParseDateF(dateStr, "yyyy-MM-dd HH:mm:ss");
                    if (dt == DateTime.MinValue) dt = ParseDateF(dateStr, "yyyy-MM-dd HH:mm:ss ffffff");
                }
                else if (dt == DateTime.MinValue && ParseDateCT(dateStr, ":", 1))
                {
                    if (dt == DateTime.MinValue) dt = ParseDateF(dateStr, "yyyy-MM-dd HH:mm");
                }
                else
                {
                    if (dt == DateTime.MinValue) dt = ParseDateF(dateStr, "yyyy-MM-dd");
                }
            }
            else if (ParseDateCT(dateStr, "-", 1))
            {
                if (dt == DateTime.MinValue) dt = ParseDateF(dateStr, "yyyy-MM");
            }
            else
            {
                if (dt == DateTime.MinValue && ParseDateCT(dateStr, ".", 1))
                {
                    if (dt == DateTime.MinValue) dt = ParseDateF(dateStr, "HH:mm:ss.ffffff");
                }
                else if (m_ParseDate_AZ.IsMatch(dateStr))
                {
                    /*类似格式(Chrome默认输出格式): Mon Mar 20 2017 02:46:06 GMT+0800 (中国标准时间)*/
                    /*类似格式(IE9默认输出格式): Mon Mar 20 02:46:06 UTC+0800 2017*/
                    if (dateStr.IndexOf("(") >= 0)
                    {
                        if (dt == DateTime.MinValue) dt = ParseDateF(dateStr, "MM dd yyyy HH:mm:ss");
                        if (dt == DateTime.MinValue) dt = ParseDateF(dateStr, "MM dd HH:mm:ss yyyy");
                    }
                    else
                    {
                        if (dt == DateTime.MinValue) dt = ParseDateF(dateStr, "MM dd HH:mm:ss yyyy");
                        if (dt == DateTime.MinValue) dt = ParseDateF(dateStr, "MM dd yyyy HH:mm:ss");
                    }
                }
                else if (dt == DateTime.MinValue && ParseDateCT(dateStr, ":", 2))
                {
                    if (dt == DateTime.MinValue) dt = ParseDateF(dateStr, "HH:mm:ss");
                    if (dt == DateTime.MinValue) dt = ParseDateF(dateStr, "HH:mm:ss ffffff");
                }
                else if (dt == DateTime.MinValue && ParseDateCT(dateStr, ":", 1))
                {
                    if (dt == DateTime.MinValue) dt = ParseDateF(dateStr, "HH:mm");
                }
            }
            return dt;
        }
        /*尝试为 ParseDateV 的 参数赋值*/
        private static void ParseDateSV(string df, string dv, ParseDateV t)
        {
            if (t == null) return;
            df = m_ParseDate_S.Replace(df, string.Empty);
            dv = m_ParseDate_S.Replace(dv, string.Empty);


            int dv2 = ToInt(dv);
            if (df == "Y" || df == "YYYY" || df == "YY" || df == "yyyy" || df == "yy" || df == "y") t.Y = dv2;
            else if (df == "M" || df == "MM" || df == "MTH" || df == "MONTH") t.M = dv2;
            else if (df == "d" || df == "dd" || df == "day") t.d = dv2;
            else if (df == "H" || df == "HH" || df == "HH24" || df == "hh24") t.H = dv2;
            else if (df == "h" || df == "hh" || df == "HH12" || df == "hh12") t.h = dv2;
            else if (df == "N" || df == "mm" || df == "MI") t.N = dv2;
            else if (df == "s" || df == "ss") t.s = dv2;
            else if (df == "S" || df == "MS" || df == "SSSSSS" || df == "SSS" || df == "SS" || df == "ffffff" || df == "fff" || df == "ff") t.S = dv2;
        }


        private static readonly Regex m_ParseDate_Date = new Regex(@"\d{1,4}\s*-\s*\d{1,2}\s*-\s*\d{1,4}", RegexOptions.IgnoreCase | RegexOptions.Compiled);
        private static readonly Regex m_ParseDate_Time = new Regex(@"\d{1,2}\s*:\s*\d{1,2}(\s*:\s*\d{1,2})*", RegexOptions.IgnoreCase | RegexOptions.Compiled);
        private static readonly Regex m_ParseDate_T = new Regex(@"(?<=\d)\s*T\s*(?=\d)", RegexOptions.IgnoreCase | RegexOptions.Compiled);
        private static readonly Regex m_ParseDate_S = new Regex(@"\s+", RegexOptions.IgnoreCase | RegexOptions.Compiled);
        private static readonly Regex m_ParseDate_N = new Regex(@"[^0-9]+", RegexOptions.IgnoreCase | RegexOptions.Compiled);
        private static readonly Regex m_ParseDate_AZ = new Regex(@"[A-Z]", RegexOptions.IgnoreCase | RegexOptions.Compiled);
        private static readonly Regex m_ParseDate_GU = new Regex(@"((GMT)|(UTC))*\+\d+", RegexOptions.IgnoreCase | RegexOptions.Compiled);
        private static readonly Regex m_ParseDate_P = new Regex(@"\([^\)]+\)", RegexOptions.IgnoreCase | RegexOptions.Compiled);
        private static readonly Regex m_ParseDate_SP = new Regex(@"\s*[:/\\-]\s*", RegexOptions.IgnoreCase | RegexOptions.Compiled);

        /*Z时区、h12小时、P上下午、W星期 暂时不提供识别*/
        private class ParseDateV
        {
            public ParseDateV()
            {
                DateTime nowTime = DateTime.Now;
                Y = nowTime.Year;
                M = nowTime.Month;
                d = nowTime.Day;
            }

            public int Y = 0;
            public int M = 0;
            public int d = 0;
            public int H = 00;
            public int h = 00;
            public int N = 00;
            public int s = 00;
            public int S = 00;
            public int Z = 0;
            public int P = 0;
            public int W = 0;
        }
        private class ParseDateD
        {
            public int idxV = 0;
            public int idxF = 0;
            public int cntFV = 0;
            public string v;
            public string f;
        }

        #endregion



        #endregion


        #region  数 据 转 换

        #region  基 本 数 据 类 型

        public static bool IsMetaType(Type type)
        {
            if (type.IsEnum) return true;       //枚举视为 基本类型
            return hashMetaTypes.ContainsKey(type);
        }
        public static Type GetTypeBySimpleTypeName(string typeName)
        {
            if (string.IsNullOrEmpty(typeName)) return null;

            switch (typeName.ToLower())
            {
                case "guid": return typeofGuid;
                case "string":
                case "str": return typeofString;
                case "bool":
                case "boolean": return typeofBoolean;
                case "byte": return typeofByte;
                case "char": return typeofChar;
                case "decimal": return typeofDecimal;
                case "double": return typeofDouble;
                case "short":
                case "int16": return typeofInt16;
                case "int":
                case "int32": return typeofInt32;
                case "long":
                case "int64": return typeofInt64;
                case "sbyte": return typeofSByte;
                case "float":
                case "single": return typeofSingle;
                case "timespan": return typeofTimeSpan;
                case "datetime": return typeofDateTime;
                case "ushort":
                case "uint16": return typeofUInt16;
                case "uint":
                case "uint32": return typeofUInt32;
                case "ulong":
                case "uint64": return typeofUInt64;
                case "object":
                case "obj": return typeofObject;
                case "byte[]":
                case "bytes": return typeofByteArray;
            }

            return Type.GetType(typeName);
        }

        internal static Assembly urtAssembly = Assembly.Load("mscorlib");//Assembly.GetAssembly(Converter.typeofString);
        internal static Type typeofString = typeof(string);
        internal static Type typeofGuid = typeof(Guid);
        internal static Type typeofBoolean = typeof(bool);
        internal static Type typeofByte = typeof(byte);
        internal static Type typeofChar = typeof(char);
        internal static Type typeofDecimal = typeof(decimal);
        internal static Type typeofDouble = typeof(double);
        internal static Type typeofInt16 = typeof(short);
        internal static Type typeofInt32 = typeof(int);
        internal static Type typeofInt64 = typeof(long);
        internal static Type typeofSByte = typeof(sbyte);
        internal static Type typeofSingle = typeof(float);
        internal static Type typeofTimeSpan = typeof(TimeSpan);
        internal static Type typeofDateTime = typeof(DateTime);
        internal static Type typeofUInt16 = typeof(ushort);
        internal static Type typeofUInt32 = typeof(uint);
        internal static Type typeofUInt64 = typeof(ulong);

        internal static Type typeofObject = typeof(object);  //不是基本数据类型
        //internal static Type typeofSystemVoid = typeof(void);
        //internal static Type typeofTypeArray = typeof(Type[]);
        //internal static Type typeofObjectArray = typeof(object[]);
        //internal static Type typeofStringArray = typeof(string[]);
        //internal static Type typeofBooleanArray = typeof(bool[]);
        internal static Type typeofByteArray = typeof(byte[]);
        //internal static Type typeofCharArray = typeof(char[]);
        //internal static Type typeofDecimalArray = typeof(decimal[]);
        //internal static Type typeofDoubleArray = typeof(double[]);
        //internal static Type typeofInt16Array = typeof(short[]);
        //internal static Type typeofInt32Array = typeof(int[]);
        //internal static Type typeofInt64Array = typeof(long[]);
        //internal static Type typeofSByteArray = typeof(sbyte[]);
        //internal static Type typeofSingleArray = typeof(float[]);
        //internal static Type typeofTimeSpanArray = typeof(TimeSpan[]);
        //internal static Type typeofDateTimeArray = typeof(DateTime[]);
        //internal static Type typeofUInt16Array = typeof(ushort[]);
        //internal static Type typeofUInt32Array = typeof(uint[]);
        //internal static Type typeofUInt64Array = typeof(ulong[]);

        internal static Hashtable hashMetaTypes = Hashtable.Synchronized(new Hashtable
                                                   {
                                                       #region  基础数据类型

                                                       { typeofString, 1},
                                                       { typeofGuid, 1},
                                                       { typeofBoolean, 1},
                                                       { typeofByte, 1},
                                                       { typeofChar, 1},
                                                       { typeofDecimal, 1},
                                                       { typeofDouble, 1},
                                                       { typeofInt16, 1},
                                                       { typeofInt32, 1},
                                                       { typeofInt64, 1},
                                                       { typeofSByte, 1},
                                                       { typeofSingle, 1},
                                                       { typeofTimeSpan, 1},
                                                       { typeofDateTime, 1},
                                                       { typeofUInt16, 1},
                                                       { typeofUInt32, 1},
                                                       { typeofUInt64, 1},
                                                       //{ typeofObject, 1},
                                                       //{ typeofSystemVoid, 1},
                                                       //{ typeofTypeArray, 1},
                                                       //{ typeofObjectArray, 1},
                                                       //{ typeofStringArray, 1},
                                                       //{ typeofBooleanArray, 1},
                                                       { typeofByteArray, 1},
                                                       //{ typeofCharArray, 1},
                                                       //{ typeofDecimalArray, 1},
                                                       //{ typeofDoubleArray, 1},
                                                       //{ typeofInt16Array, 1},
                                                       //{ typeofInt32Array, 1},
                                                       //{ typeofInt64Array, 1},
                                                       //{ typeofSByteArray, 1},
                                                       //{ typeofSingleArray, 1},
                                                       //{ typeofTimeSpanArray, 1},
                                                       //{ typeofDateTimeArray, 1},
                                                       //{ typeofUInt16Array, 1},
                                                       //{ typeofUInt32Array, 1},
                                                       //{ typeofUInt64Array, 1},
                                                       #endregion
                                                   });

        #endregion

        public static object ChangeType(object obj, Type type)
        {
            if (type == null || type == typeofObject) return obj;
            if (obj == DBNull.Value || obj == null) return DefaultForType(type);

            Type objType = obj.GetType();
            if (objType == type || type.IsAssignableFrom(objType)) return obj;

            try
            {
                #region  转 换 类 型

                if (type == typeofBoolean) return ToBoolean(obj);
                if (type == typeofChar) return ToChar(obj);
                if (type == typeofSByte) return (sbyte)ToByte(obj);
                if (type == typeofByte) return ToByte(obj);
                if (type == typeofInt16) return ToShort(obj);
                if (type == typeofUInt16) return (ushort)ToDouble(obj);
                if (type == typeofInt32) return ToInt(obj);
                if (type == typeofUInt32) return (uint)ToDouble(obj);
                if (type == typeofInt64) return ToLong(obj);
                if (type == typeofUInt64) return (ulong)ToDouble(obj);
                if (type == typeofSingle) return ToFloat(obj);
                if (type == typeofDouble) return ToDouble(obj);
                if (type == typeofDecimal) return ToDecimal(obj);
                if (type == typeofDateTime) return ToDateTime(obj);
                if (type == typeofString) return ToString(obj);
                if (type == typeofGuid) return ToGuid(obj);
                if (type == typeofObject) return obj;

                #endregion

                return Convert.ChangeType(obj, type);
            }
            catch (System.Threading.ThreadAbortException) { throw; }
            catch (Exception exp)
            {
                throw new InvalidCastException(string.Format("ChangeType(object, Type) Error: Value: '{0}' Can Not Cast To Type: '{1}' (InnerException: {2})", obj, type, exp.Message));
            }
        }
        public static object DefaultForType(Type type)
        {
            if (type == null) return null;
            return type.IsValueType ? Activator.CreateInstance(type) : null;
        }

        #endregion

        
        #region  时 间 戳 函 数

        private static DateTime m_StampRoot = new DateTime(1970, 01, 01, 00, 00, 00, 00, DateTimeKind.Utc);
        private static readonly Regex m_RegNum = new Regex(@"\d+", RegexOptions.Compiled | RegexOptions.IgnoreCase);

        /// <summary>
        /// Json时间戳 转 时间
        /// </summary>
        public static DateTime StampToLocalDateTime(string timeStamp)
        {
            return StampToDateTime(timeStamp, DateTimeKind.Local);
        }
        /// <summary>
        /// Json时间戳 转 时间
        /// </summary>
        public static DateTime StampToUtcDateTime(string timeStamp)
        {
            return StampToDateTime(timeStamp, DateTimeKind.Utc);
        }
        /// <summary>
        /// Json时间戳 转 时间
        /// </summary>
        public static DateTime StampToDateTime(string timeStamp, DateTimeKind kind)
        {
            Match match = m_RegNum.Match(timeStamp);
            if (!match.Success) return m_StampRoot;
            long num = long.Parse(match.Value);

            if (kind == DateTimeKind.Utc) return StampToUtcDateTime(num);
            else return StampToLocalDateTime(num);
        }
        /// <summary>
        /// Json时间戳 转 时间
        /// </summary>
        public static DateTime StampToLocalDateTime(long timeStamp)
        {
            return m_StampRoot.AddMilliseconds(timeStamp).ToLocalTime();
        }
        /// <summary>
        /// Json时间戳 转 时间
        /// </summary>
        public static DateTime StampToUtcDateTime(long timeStamp)
        {
            return m_StampRoot.AddMilliseconds(timeStamp).ToUniversalTime();
        }
        /// <summary>
        /// 时间 转 Json时间戳
        /// </summary>
        public static long DateTimeToStamp(DateTime time)
        {
            return (long)(time.ToUniversalTime() - m_StampRoot).TotalMilliseconds;
        }

        #endregion


        #region  编 码 ID

        private static readonly object m_GetTimeIDLocker = new object();
        private static long m_LastGetTimeID;

        /// <summary>
        /// 获取一个新的 Guid
        /// </summary>
        public static Guid NewGuid()
        {
            return Guid.NewGuid();
        }
        /// <summary>
        /// 获取一个新的 Guid, 并返回这个 Guid的 大写无分隔符的 编号
        /// </summary>
        public static string NewGuidNo()
        {
            Guid guid = Guid.NewGuid();
            return guid.ToString("N").ToUpper();
        }
        /// <summary>
        /// 获取一个 基于时间的 不重复的 增量 ID (这个ID 可能是 不连续的, 且勉强只能确保在 内存中 不重复)
        /// </summary>
        public static long NewTimeID()
        {
            lock (m_GetTimeIDLocker)
            {
                long value = Convert.ToInt64(DateTime.Now.ToString("yyyyMMddHHmmssffffff"));
                if (value <= m_LastGetTimeID)
                    value = m_LastGetTimeID + 1L;
                m_LastGetTimeID = value;
                return value;
            }
        }
        /// <summary>
        /// 获取一个 基于时间的 不重复的 增量编号, 如果可以, 不建议使用本函数, 而是Guid (这个编号 可能是 不连续的, 且勉强只能确保在 内存中 不重复)
        /// </summary>
        public static string NewTimeNo()
        {
            long value = NewTimeID();
            return HexBinDecOct(value, 36).PadRight(14, '0');
        }

        private static string HexBinDecOct(long value, int step)
        {
            if (step > 36)
                throw new Exception("Max Target Number System Is Thirty-Six!");
            string str = string.Empty;
            long num1 = value;
            while (num1 >= (long)step)
            {
                long num2 = num1 % (long)step;
                num1 /= (long)step;
                str = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[(int)num2] + str;
            }
            if (num1 > 0L)
                str = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[(int)num1] + str;
            return str;
        }


        #endregion


        #region  读 写 配 置 文 件

        private static ConfigAppSetting m_AppSettings;
        private static ConfigConnectionStrings m_ConnectionStrings;

        public static ConfigAppSetting AppSettings
        {
            get
            {
                if (m_AppSettings == null)
                {
                    m_AppSettings = new ConfigAppSetting();
                    m_AppSettings.AppSettingChanged += OnAppSettingChanged;
                }
                return m_AppSettings;
            }
        }
        public static ConfigConnectionStrings ConnectionStrings
        {
            get
            {
                if (m_ConnectionStrings == null)
                {
                    m_ConnectionStrings = new ConfigConnectionStrings();
                    m_ConnectionStrings.ConnectionStringsChanged += OnConnectionStringsChanged;
                }
                return m_ConnectionStrings;
            }
        }


        private static void OnAppSettingChanged(string name, string value)
        {
            string configPath = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
            if (!File.Exists(configPath))
            {
                const string content = @"<?xml version=""1.0""?><configuration></configuration>";
                File.WriteAllText(configPath, content, Encoding.UTF8);
            }

            XmlDocument doc = new XmlDocument();
            doc.Load(configPath);

            XmlNode nodeConfiguration = doc.SelectSingleNode(@"configuration");
            if (nodeConfiguration == null)
            {
                nodeConfiguration = doc.CreateNode(XmlNodeType.Element, "configuration", string.Empty);
                doc.AppendChild(nodeConfiguration);
            }

            XmlNode nodeAppSettings = nodeConfiguration.SelectSingleNode(@"appSettings");
            if (nodeAppSettings == null)
            {
                nodeAppSettings = doc.CreateNode(XmlNodeType.Element, "appSettings", string.Empty);
                if (!nodeConfiguration.HasChildNodes)
                    nodeConfiguration.AppendChild(nodeAppSettings);
                else
                {
                    //configSections 必须放在 第一个, 所以得 避开 configSections
                    XmlNode firstNode = nodeConfiguration.ChildNodes[0];
                    bool firstNodeIsSections = string.Equals(firstNode.Name, "configSections", StringComparison.CurrentCultureIgnoreCase);

                    if (firstNodeIsSections)
                        nodeConfiguration.InsertAfter(nodeAppSettings, firstNode);
                    else
                        nodeConfiguration.InsertBefore(nodeAppSettings, firstNode);
                }
            }

            string xmlName = FormatXmlStr(name);
            XmlNode nodeAdd = nodeAppSettings.SelectSingleNode(@"add[@key='" + xmlName + "']");
            if (nodeAdd == null)
            {
                nodeAdd = doc.CreateNode(XmlNodeType.Element, "add", string.Empty);
                nodeAppSettings.AppendChild(nodeAdd);
            }

            XmlElement nodeElem = (XmlElement)nodeAdd;
            nodeElem.SetAttribute("key", name);
            nodeElem.SetAttribute("value", value);
            doc.Save(configPath);

            try { ConfigurationManager.RefreshSection("appSettings"); }
            catch (System.Threading.ThreadAbortException) { throw; }
            catch (Exception ex) { Tools.LogWarn(ex); }
        }
        private static void OnConnectionStringsChanged(string name, string value)
        {
            string configPath = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
            if (!File.Exists(configPath))
            {
                const string content = @"<?xml version=""1.0""?><configuration></configuration>";
                File.WriteAllText(configPath, content, Encoding.UTF8);
            }

            XmlDocument doc = new XmlDocument();
            doc.Load(configPath);

            XmlNode nodeConfiguration = doc.SelectSingleNode(@"configuration");
            if (nodeConfiguration == null)
            {
                nodeConfiguration = doc.CreateNode(XmlNodeType.Element, "configuration", string.Empty);
                doc.AppendChild(nodeConfiguration);
            }

            XmlNode nodeAppSettings = nodeConfiguration.SelectSingleNode(@"appSettings");
            XmlNode nodeConnectionStrings = nodeConfiguration.SelectSingleNode(@"connectionStrings");
            if (nodeConnectionStrings == null)
            {
                nodeConnectionStrings = doc.CreateNode(XmlNodeType.Element, "connectionStrings", string.Empty);
                if (!nodeConfiguration.HasChildNodes)
                    nodeConfiguration.AppendChild(nodeConnectionStrings);
                else
                {
                    //优先将 connectionStrings 放在 appSettings 后面
                    if (nodeAppSettings != null)
                        nodeConfiguration.InsertAfter(nodeConnectionStrings, nodeAppSettings);
                    else
                    {
                        //如果 没有 appSettings 节点, 则 configSections 必须放在 第一个, 所以得 避开 configSections
                        XmlNode firstNode = nodeConfiguration.ChildNodes[0];
                        bool firstNodeIsSections = string.Equals(firstNode.Name, "configSections", StringComparison.CurrentCultureIgnoreCase);

                        if (firstNodeIsSections)
                            nodeConfiguration.InsertAfter(nodeConnectionStrings, firstNode);
                        else
                            nodeConfiguration.InsertBefore(nodeConnectionStrings, firstNode);
                    }
                }
            }

            string xmlName = FormatXmlStr(name);
            XmlNode nodeAdd = nodeConnectionStrings.SelectSingleNode(@"add[@name='" + xmlName + "']");
            if (nodeAdd == null)
            {
                nodeAdd = doc.CreateNode(XmlNodeType.Element, "add", string.Empty);
                nodeConnectionStrings.AppendChild(nodeAdd);
            }

            XmlElement nodeElem = (XmlElement)nodeAdd;
            nodeElem.SetAttribute("name", name);
            nodeElem.SetAttribute("connectionString", value);
            doc.Save(configPath);

            try
            {
                ConfigurationManager.RefreshSection("connectionString");  //RefreshSection 无法刷新 connectionString 节点
                FieldInfo fieldInfo = typeof(ConfigurationManager).GetField("s_initState", BindingFlags.NonPublic | BindingFlags.Static);
                if (fieldInfo != null) fieldInfo.SetValue(null, 0);       //将配置文件 设置为: 未分析 状态, 配置文件 将会在下次读取 时 重新分析.
            }
            catch (System.Threading.ThreadAbortException) { throw; }
            catch (Exception ex) { Tools.LogWarn(ex); }
        }

        private static string FormatXmlStr(string value)
        {
            if (string.IsNullOrEmpty(value)) return string.Empty;

            string result = value
                .Replace("<", "&lt;")
                .Replace(">", "&gt;")
                .Replace("&", "&amp;")
                .Replace("'", "&apos;")
                .Replace("\"", "&quot;");
            return result;
            //&lt; < 小于号 
            //&gt; > 大于号 
            //&amp; & 和 
            //&apos; ' 单引号 
            //&quot; " 双引号 
        }


        public class ConfigAppSetting
        {
            private readonly InnerIgnoreDict<string> m_Hash = new InnerIgnoreDict<string>();

            public string this[string name]
            {
                get
                {
                    string value = m_Hash[name];
                    if (IsNullOrWhiteSpace(value))
                    {
                        try { value = ConfigurationManager.AppSettings[name]; }
                        catch (System.Threading.ThreadAbortException) { throw; }
                        catch (Exception ex) { Tools.LogWarn(ex); }
                        m_Hash[name] = value;
                        return value;
                    }
                    return value;
                }
                set
                {
                    m_Hash[name] = value;
                    try { ConfigurationManager.AppSettings[name] = value; }
                    catch (System.Threading.ThreadAbortException) { throw; }
                    catch (Exception ex) { Tools.LogWarn(ex); }
                    if (AppSettingChanged != null) AppSettingChanged(name, value);
                }
            }
            public AppSettingValueChanged AppSettingChanged;

            public delegate void AppSettingValueChanged(string name, string value);
        }
        public class ConfigConnectionStrings
        {
            private readonly InnerIgnoreDict<ConnectionStringSettings> m_Hash = new InnerIgnoreDict<ConnectionStringSettings>();

            public string this[string name]
            {
                get
                {
                    ConnectionStringSettings value = m_Hash[name];
                    if (value == null || IsNullOrWhiteSpace(value.ConnectionString))
                    {
                        try { value = ConfigurationManager.ConnectionStrings[name]; }
                        catch (System.Threading.ThreadAbortException) { throw; }
                        catch (Exception ex) { LogWarn(ex); }
                        m_Hash[name] = value;
                        return value == null ? string.Empty : value.ConnectionString;
                    }
                    return value.ConnectionString;
                }
                set
                {
                    ConnectionStringSettings setting = new ConnectionStringSettings();
                    setting.Name = name;
                    setting.ConnectionString = value;
                    m_Hash[name] = setting;
                    //try { ConfigurationManager.ConnectionStrings[name] = setting; } catch (System.Threading.ThreadAbortException) { throw; } catch (Exception ex) { Tools.LogWarn(ex); }
                    if (ConnectionStringsChanged != null) ConnectionStringsChanged(name, value);
                }
            }
            public ConnectionStringsValueChanged ConnectionStringsChanged;

            public delegate void ConnectionStringsValueChanged(string name, string value);
        }



        private class InnerIgnoreDict<T> : Dictionary<string, T>
        {
            public InnerIgnoreDict()
                : base(StringComparer.CurrentCultureIgnoreCase)
            {
            }

#if (!WindowsCE && !PocketPC)
            public InnerIgnoreDict(SerializationInfo info, StreamingContext context) : base(info, context) { }
#endif

            private readonly object getSetLocker = new object();
            private static readonly T defaultValue = default(T);

            public new T this[string key]
            {
                get
                {
                    if (key == null) return defaultValue;
                    lock (getSetLocker) //为了 多线程的 高并发, 取值也 加上 线程锁
                    {
                        T record;
                        if (TryGetValue(key, out record)) return record;
                        else return defaultValue;
                    }
                }
                set
                {
                    try
                    {
                        if (key != null)
                        {
                            lock (getSetLocker)
                            {
                                //if (!value.Equals(default(T)))
                                //{
                                if (base.ContainsKey(key)) base[key] = value;
                                else base.Add(key, value);
                                //}
                                //else
                                //{
                                //    base.Remove(key);
                                //}
                            }
                        }
                    }
                    catch (System.Threading.ThreadAbortException) { throw; }
                    catch (Exception ex) { Tools.LogWarn(ex); }
                }
            }
        }

        #endregion


        #region  日 志 记 录

        public static void LogDebug(string msg)
        {
            ProcessLog(LogLevel.DEBUG, null, msg, null);
        }
        public static void LogInfo(string msg)
        {
            ProcessLog(LogLevel.INFO, null, msg, null);
        }
        public static void LogOK(string msg)
        {
            ProcessLog(LogLevel.OK, null, msg, null);
        }
        public static void LogWarn(string msg)
        {
            ProcessLog(LogLevel.WARN, null, msg, null);
        }
        public static void LogWarn(Exception err)
        {
            ProcessLog(LogLevel.WARN, null, null, err);
        }
        public static void LogWarn2(Exception err, string msg)
        {
            ProcessLog(LogLevel.WARN, null, msg, err);
        }
        public static void LogError(string msg)
        {
            ProcessLog(LogLevel.ERROR, null, msg, null);
        }
        public static void LogError(Exception err)
        {
            ProcessLog(LogLevel.ERROR, null, null, err);
        }
        public static void LogError2(Exception err, string msg)
        {
            ProcessLog(LogLevel.ERROR, null, msg, err);
        }
        public static void LogFatal(string msg)
        {
            ProcessLog(LogLevel.FATAL, null, msg, null);
        }
        public static void LogFatal(Exception err)
        {
            ProcessLog(LogLevel.FATAL, null, null, err);
        }
        public static void LogFatal2(Exception err, string msg)
        {
            ProcessLog(LogLevel.FATAL, null, msg, err);
        }

        public static void LogDebug(string name, string msg)
        {
            ProcessLog(LogLevel.DEBUG, name, msg, null);
        }
        public static void LogInfo(string name, string msg)
        {
            ProcessLog(LogLevel.INFO, name, msg, null);
        }
        public static void LogOK(string name, string msg)
        {
            ProcessLog(LogLevel.OK, name, msg, null);
        }
        public static void LogWarn(string name, string msg)
        {
            ProcessLog(LogLevel.WARN, name, msg, null);
        }
        public static void LogWarn(string name, Exception err)
        {
            ProcessLog(LogLevel.WARN, name, null, err);
        }
        public static void LogWarn2(string name, Exception err, string msg)
        {
            ProcessLog(LogLevel.WARN, name, msg, err);
        }
        public static void LogError(string name, string msg)
        {
            ProcessLog(LogLevel.ERROR, name, msg, null);
        }
        public static void LogError(string name, Exception err)
        {
            ProcessLog(LogLevel.ERROR, name, null, err);
        }
        public static void LogError2(string name, Exception err, string msg)
        {
            ProcessLog(LogLevel.ERROR, name, msg, err);
        }
        public static void LogFatal(string name, string msg)
        {
            ProcessLog(LogLevel.FATAL, name, msg, null);
        }
        public static void LogFatal(string name, Exception err)
        {
            ProcessLog(LogLevel.FATAL, name, null, err);
        }
        public static void LogFatal2(string name, Exception err, string msg)
        {
            ProcessLog(LogLevel.FATAL, name, msg, err);
        }




        #region  日 志 核 心


        private static string m_LogFolder = string.Empty;
        private static bool m_KeepConsole = false;
        private static ProcessLogHandler m_ProcessLog;
        private static readonly object m_LogFileLocker = new object();
        private static readonly object m_LogConsoleLocker = new object();


        public static string LogFolder
        {
            get
            {
                if (IsNullOrWhiteSpace(m_LogFolder))
                {
                    string appFolder = AppFolder;
                    string folder = (AppSettings["Tools:LogFolder"] ?? string.Empty);
                    if (IsNullOrWhiteSpace(folder))
                        m_LogFolder = appFolder.TrimEnd('\\', '/') + @"\Logs\";
                    else if (folder.IndexOf(':') < 0)
                        m_LogFolder = appFolder.TrimEnd('\\', '/') + @"\" + folder.Trim('\\', '/') + @"\";

                    //if (Directory.Exists(m_LogFolder)) Directory.CreateDirectory(m_LogFolder);
                }
                return m_LogFolder;
            }
        }
        public static void RegLogHandler(bool keepConsole, ProcessLogHandler handler)
        {
            lock (m_LogFileLocker)
            {
                m_ProcessLog = handler;
                m_KeepConsole = keepConsole;
            }
        }
        private static void ProcessLog(LogLevel level, string name, string msg, Exception err)
        {
            if (m_ProcessLog != null)
            {
                m_ProcessLog((int)level, name, msg, err);
                if (!m_KeepConsole || !IsConsole) return;
            }

            string log = GetLogString(level, msg, err);
            ProcessLogConsole(level, log);
            if (m_ProcessLog == null) ProcessLogFile(level, name, log);
        }

        private static void ProcessLogFile(LogLevel level, string name, string log)
        {
            lock (m_LogFileLocker)
            {
                try
                {
                    string fileName = string.IsNullOrEmpty(name)
                        ? string.Format("{1:yyyyMMdd}.log", name, DateTime.Now)
                        : string.Format("{0}_{1:yyyyMMdd}.log", name, DateTime.Now);

                    string path = LogFolder;
                    if (!Directory.Exists(path)) Directory.CreateDirectory(path);
                    string path2 = path + fileName;
                    System.IO.File.AppendAllText(path2, log + "\r\n", Encoding.UTF8);
                }
                catch (ThreadAbortException) { throw; }
                catch (Exception ex) { Console.WriteLine(ex); }
            }
        } 
        private static void ProcessLogConsole(LogLevel level, string log)
        {
            if (Tools.IsConsole)
            {
                lock (m_LogConsoleLocker)
                {
                    ConsoleColor oldColor = Console.ForegroundColor;
                    try
                    {
                        if (level == LogLevel.INFO) Console.ForegroundColor = ConsoleColor.Cyan;
                        else if (level == LogLevel.DEBUG) Console.ForegroundColor = ConsoleColor.White;
                        else if (level == LogLevel.WARN) Console.ForegroundColor = ConsoleColor.Yellow;
                        else if (level == LogLevel.ERROR) Console.ForegroundColor = ConsoleColor.Red;
                        else if (level == LogLevel.FATAL) Console.ForegroundColor = ConsoleColor.Magenta;
                        else if (level == LogLevel.OK) Console.ForegroundColor = ConsoleColor.Green;
                        Console.WriteLine(ToShortString(log.Trim()));
                    }
                    catch (ThreadAbortException) { throw; }
                    catch (Exception ex) { Console.WriteLine(ex); }
                    finally { Console.ForegroundColor = oldColor; }
                }
            }
        }

        private static string GetLogString(LogLevel level, string msg, Exception err)
        {
            DateTime time = DateTime.Now;
            StringBuilder sb = new StringBuilder();
            sb.Append("[" + time.ToString("yyyy-MM-dd HH:mm:ss ffffff") + "] ");
            sb.Append(("[" + level.ToString().ToUpper() + "] ").PadRight(8, ' '));
            if (!string.IsNullOrEmpty(msg))
            {
                sb.Append(msg);
                if (err != null) sb.Append(" > " + err.Message);
                if (err != null && err.InnerException != null) sb.Append(" > " + err.InnerException.Message);
            }
            else
            {
                if (err != null) sb.Append(err.Message);
                if (err != null && err.InnerException != null) sb.Append(" > " + err.InnerException.Message);
            }

            if (err != null)
            {
                sb.AppendLine();
                sb.AppendLine("-------------------------------------------");
                sb.AppendLine(err.StackTrace);
                sb.AppendLine("-------------------------------------------");
                sb.AppendLine();
            }

            string str = sb.ToString();
            return str;
        }
        private static string ToShortString(string str)
        {
            if (Tools.IsNullOrWhiteSpace(str)) return str;
            if (str.Length < 5000) return str;
            return str.Substring(0, 2500) + " ...[" + (str.Length - 5000) + "个字符未显示]... " + str.Substring(str.Length - 2500);
        }
        

        [Serializable]
        private enum LogLevel
        {
            DEBUG=0,
            INFO,
            OK,
            WARN,
            ERROR,
            FATAL
        }

        #endregion

        #endregion


        #region  其 他 函 数

        /// <summary>
        /// 将 #ffffff 0xffffff #fff #ffffffff 这类数据, 转换成一个 颜色
        /// </summary>
        public static Color ColorFromHex(string hexString)
        {
            string cleanHex = hexString.Replace("#", "").Replace("0x", "");
            // turn #FFF into #FFFFFF
            if (cleanHex.Length == 3)
            {
                cleanHex = "" + cleanHex[0] + cleanHex[0] + cleanHex[1] + cleanHex[1] + cleanHex[2] + cleanHex[2];
            }
            // add an alpha 100% if it is missing
            if (cleanHex.Length == 6)
            {
                cleanHex = "FF" + cleanHex;
            }
            int argb = Int32.Parse(cleanHex, NumberStyles.HexNumber);
            Color clr = Color.FromArgb((byte)((argb & 0xff000000) >> 0x18),
                              (byte)((argb & 0xff0000) >> 0x10),
                              (byte)((argb & 0xff00) >> 8),
                              (byte)(argb & 0xff));
            return clr;
        }


        #endregion

    }

    /// <summary>
    /// 额外处理 日志的委托 (调用 Tools.RegLogHandler(*) 后, 日志的记录将不再使用内置的 日志记录方式)
    /// </summary>
    /// <param name="level">分别对应 DEBUG=0, INFO=1, OK=2, WARN=3, ERROR=4, FATAL=5</param>
    /// <param name="name">日志名称分类</param>
    /// <param name="msg">日志正文</param>
    /// <param name="err">日志异常信息</param>
    public delegate void ProcessLogHandler(int level, string name, string msg, Exception err);
}
